一、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();
//主线程继续执行
标签:Thread,t1,线程,打断,sleep,logger,方法,类中
From: https://www.cnblogs.com/chengxuxiaoyuan/p/16819457.html