Sleep
/**
* 验证当sleep时,线程被打断
* @throws InterruptedException
*/
@Test
public void test1() throws InterruptedException {
Thread t1 = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(2);
System.out.println("子线程执行了");
} catch (InterruptedException e) {
e.printStackTrace(); //当线程t1被打断时,就会走到catch里,“子线程执行了”这条语句不会输出了
}
});
t1.start();
TimeUnit.SECONDS.sleep(1);
t1.interrupt(); //通过main线程打断睡眠中的t1线程
}
/**
* 验证线程在sleep的时候,线程状态是什么
* @throws InterruptedException
*/
@Test
public void test2() throws InterruptedException {
Thread t1 = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t1.start();
TimeUnit.SECONDS.sleep(1); //睡眠1s是为了更好的测试,让t1先执行,在t1睡眠的过程中通过main线程调用t1的getstate方法来查看状态
System.out.println(t1.getState()); //TIMED_WAITING,当t1线程睡眠时,他的状态就是TIMED_WAITING
}
yield
yield会让当前线程让出cpu的使用权,但是可能出现让出使用权后,又获取到cpu的时间片
sleep与yield区别
当执行这两个方法后,都会释放cpu使用权,yield会重新竞争cpu使用权,但是sleep需要等待设置的超时时间完成之后才会竞争
join
/**
* 验证join的使用
* @throws InterruptedException
*/
int a=1;
@Test
public void test3() throws InterruptedException {
Thread t1 = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
a = 10;
});
t1.start();
t1.join(); //直到t1线程执行完毕,后面的代码才会执行,这就是join的作用
System.out.println(a);
}
interrupt
-
isInterrupted()方法,返回打断标记状态
1)打断阻塞的线程(一般是调用了sleep,wait,join方法。join底层就是wait),会把打断标记复位/** * 当一个线程处于被阻塞状态或者试图执行一个阻塞操作时,使用Thread.interrupt()方式中断该线程, * 注意此时将会抛出一个InterruptedException的异常,同时中断状态将会被复位(由中断状态改为非中断状态) * @throws InterruptedException */ @Test public void test4() throws InterruptedException { Thread t1 = new Thread(() -> { try { System.out.println("t1............sleep"); TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } }); t1.start(); TimeUnit.SECONDS.sleep(1); System.out.println("interrupt.........."); t1.interrupt(); boolean interrupted = t1.isInterrupted(); System.out.println("打断标记为:"+interrupted); //false }
2)打断正常的线程
/**
* 验证interrupt打断正常的线程时,
* 注意打断线程并不是线程就停止了,线程不会有任何的响应
* 想要停止,就必须使用isInterrupted的返回值来判断是否结束线程
* @throws InterruptedException
*/
public class InterruptThread2 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread() {
@Override
public void run() {
while (true) {
System.out.println("未被中断");
}
}
};
t1.start();
TimeUnit.SECONDS.sleep(2);
t1.interrupt();
/*
* 输出结果(无限执行):
未被中断
未被中断
未被中断
......
*/
// 虽然我们调用了interrupt方法,但线程t1并未被中断,因为处于非阻塞状态的线程需要我们手动进行中断检测并结束程序
}
}
park方法以及interrupted()方法
package com.che.springbootdemo.thread;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
/**
* @author cyh
* @Description
* @date 2022/4/10 20:20
*/
@Slf4j
public class Park {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
log.debug("park....");
LockSupport.park();
log.debug("unpark111111.......");
log.debug("打断状态:{}", Thread.currentThread().isInterrupted());
LockSupport.park(); //此处已经park住了,但是后面的代码还是会执行,
// 因为上面的打断标记已经是true了,所以下面n次park都会执行,如果想park住,
// 可以将Thread.currentThread().isInterrupted()替换成Thread.interrupted(),
//他的作用就是返回打断标记,并将标记重新置为false,当打断标记为false时,就能park住
log.debug("unpark22222.......");
}, "t1");
t1.start();
TimeUnit.SECONDS.sleep(1);
t1.interrupt();
}
}
/**
* 运行结果
* 20:27:02.425 [t1] DEBUG com.che.springbootdemo.thread.Park - park....
* 20:27:03.423 [t1] DEBUG com.che.springbootdemo.thread.Park - unpark111111.......
* 20:27:03.423 [t1] DEBUG com.che.springbootdemo.thread.Park - 打断状态:true
* 20:27:03.424 [t1] DEBUG com.che.springbootdemo.thread.Park - unpark22222.......
*/