1、线程打断相关的方法
* 所谓的打断并非是中断线程,而是设置线程的标识位,将默认false设置为true
* interrupt() 设置标识位
* isInterrupted() 查询标识位
* static interrupted() 查询当前线程标识位,并重置为false
example1
@Test
public void function1() throws InterruptedException {
Thread t1 = new Thread(()->{
for(;;){
if (Thread.currentThread().isInterrupted()){
System.out.println("t1 被修改了标识位");
System.out.println(Thread.currentThread().isInterrupted());
Thread.interrupted();
System.out.println(Thread.currentThread().isInterrupted());
}
}
});
t1.start();
TimeUnit.SECONDS.sleep(2);
t1.interrupt();
}
console log
t1 被修改了标识位
true
false
2、interrupt() 与sleep()、wait()、join()
example2
@Test
public void function2(){
Thread t2 = new Thread(()->{
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
System.out.println("睡眠中的t2线程,被设置标识位,即调用interrupt()方法触发InterruptedException异常");
//获取当前线程的标识位,依旧为false,原因调用interrupt()方法后成功设置为true,但是由于触发异常,java机制又将其恢复为默认值false
System.out.println(Thread.currentThread().isInterrupted());
}
});
t2.start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.interrupt();
}
console log
睡眠中的t2线程,被设置标识位,即调用interrupt()方法触发InterruptedException异常
false
3、interrupt()与wait()
example
@Test
public void function3(){
final Object o = new Object();
Thread t3 = new Thread(()->{
synchronized (o){
try {
o.wait();
} catch (InterruptedException e) {
// e.printStackTrace();
System.out.println("等待状态下的t3线程被设置标识位,触发InterruptedException异常");
//同样线程标识位被java机制恢复为默认值false
System.out.println(Thread.currentThread().isInterrupted());
}
}
});
t3.start();
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
t3.interrupt();
}
console log
等待状态下的t3线程被设置标识位,触发InterruptedException异常
false
4、 interrupt()与synchronized
* interrupt()给线程设置标识位,不会影响线程竞争锁,不会抛出InterruptedException异常
* 线程t4先持有锁,睡10秒后释放锁,t4持有锁期间,虽然线程t5被设置了标识位,t4执行完t5依旧可以正常获得锁并执行
example
@Test
public void function4(){
final Object o = new Object();
Thread t4 = new Thread(()->{
synchronized (o){
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t4.start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
Thread t5 = new Thread(()->{
synchronized (o){
}
System.out.println("t5 end");
});
t5.start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
t5.interrupt();
}
console log
t5 end
5、interrupt()与JUC下的LOCK
* 如果采用reentrantLock.lock()争抢锁的方式,interrupt()不会影响线程竞争JUC下的LOCK
example
@Test
public void function5(){
final ReentrantLock reentrantLock = new ReentrantLock();
Thread t6 = new Thread(()->{
reentrantLock.lock();
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
System.out.println("t6 end");
});
t6.start();
//主线程睡1秒
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
Thread t7 = new Thread(()->{
reentrantLock.lock();
try {
} finally {
reentrantLock.unlock();
}
System.out.println("t7 end");
});
t7.start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
t7.interrupt();
}
6、interrupt()与JUC下的LOCK
* 如果采用reentrantLock.lockInterruptibly()争抢锁的方式,interrupt()会影响线程竞争JUC下的LOCK
example
@Test
public void function6(){
final ReentrantLock reentrantLock = new ReentrantLock();
Thread t8 = new Thread(()->{
reentrantLock.lock();
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
System.out.println("t8 end");
});
t8.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Thread t9 = new Thread(()->{
System.out.println("t9 start");
try {
reentrantLock.lockInterruptibly();
} catch (InterruptedException e) {
// 调用interrupt()方法后,会抛异常,catch块中决定是否继续争抢锁,逻辑自己控制
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
System.out.println("t9 end");
});
t9.start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
t9.interrupt();
}
注意,尽量不要用Junit单元测试模拟演示线程相关的程序,可能会演示不出预计的效果,原因是junit测试时@test方法执行完就会终止所有用户线程,尽量用main方法