一、sleep和yield方法

sleep:当前线程暂停执行,让出cpu时间片,当前线程会从Runnable进入timed waiting状态

yield:调用yield方法当前线程会让出cpu,从运行状态进入就绪状态(操作系统层面)

但具体能否让出成功依赖与操作系统的任务调度器

二、interrupt方法

打断方法,可以用来打断正常运行的方法,也可以用来打断阻塞状态(sleep,wait,join)的线程,两种打断的情况是不一样的。

线程对象上有一个打断标记Thread.currentThread().isInterrupted(),初始值是false

2.1 打断正常运行的线程

当一个正常运行的线程被打断时,这个打断标记会被设置成true,但不会真正影响此线程的执行,具体是否响应这次打断由线程自己决定

Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    logger.debug("线程t1开始运行");
                    if(Thread.currentThread().isInterrupted()){
                        logger.debug("此线程被打断了");
                        break;
                    }
                }
            }
        },"t1");
        t1.start();
        //一秒后主线程打断线程t1
        Thread.sleep(1000);
        //打断t1线程
        t1.interrupt();

上边的代码t1线程是一个死循环,1s后被主线程打断,打断标记被设为true,此线程自己决定退出循环结束运行。

2.2 打断阻塞状态的线程

当一个sleep的线程被打断时,会抛出InterruptedException异常,打断标记会先被改为true,然后被清空,也就是维持false不变.

Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    logger.debug("t1 is run");
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    logger.debug("被打断了,打断标记:{}",Thread.currentThread().isInterrupted());
                }
            }
        },"t1");
        t1.start();
        Thread.sleep(1000);
        //打断睡眠的线程t1
        t1.interrupt();

上边的线程t1 1s后被主线程打断,会抛出异常,但打断标记还是false

2.3 两阶段终止设计模式

这是interrupt方法的一个应用,用来优雅的结束一个线程。线程1调用线程2的打断,线程2自己处理完结束前的操作后自己结束。

public class Test2 {

    public static void main(String[] args) throws InterruptedException {
        Monitor monitor = new Monitor();
        monitor.start();
        // 2秒后执行停止
        Thread.sleep(3000);
        monitor.stop();
    }

}
//建设器类,有一个线程一直在监控
class Monitor{
    static Logger logger = LoggerFactory.getLogger(Monitor.class);
    Thread t;
    //开始监控的方法
    public void start(){
        t = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    Thread current =Thread.currentThread();
                    //情况1:正常运行时被打断
                    //情况2:睡眠过程中被打断,自己手动设置打断标记后在下次循环时退出
                    if(current.isInterrupted()){
                        //被打断了
                        logger.debug("被打断了,执行结束前的操作");
                        break;
                    }
                    //没有被打断时
                    try {
                        //每隔一秒执行一次监控逻辑
                        Thread.sleep(1000);
                        logger.debug("执行监控逻辑");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        //进到这里表示是睡眠过程中被打断了,需要重新设置打断标记为true,也就是自己打断一次
                        //然后再下次循环时就会自己退出
                        current.interrupt();
                    }
                }
            }
        },"t1");
        t.start();
    }

    //停止监视器的方法
    public void stop(){
        t.interrupt();
    }
}

总结:有一个监控线程一直在运行,另一个线程调用其打断方法使其结束,打断时此线程有可能在睡眠,也有可能在执行其他逻辑,所以打断后就有两种不同的处理方式。

三、join方法

join方法用来让当前线程等待调用join的那个线程等待结束。

public class Test3 {
    static Logger logger = LoggerFactory.getLogger(Test3.class);
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    logger.debug("t1 is start");
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"t1");
        t.start();
        t.join();
        logger.debug("主线程执行结束");
    }
}

上边的代码主线程会等待线程t1执行结束后才会继续执行。如果主线程需要等待多个线程执行完,只需要全部线程启动完成后调用多个join就行

t1.start();
t2.start();
t3.start();
t1.join();
t2.join();
t3.join();
//主线程继续执行

原文地址:http://www.cnblogs.com/chengxuxiaoyuan/p/16819457.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性