1. 在sleep时如果这个线程发生中断,也只是将堵塞状态变为非堵塞状态
package info;
import java.util.concurrent.*;
public class Factory implements Runnable{
public void run() {
System.out.println("begin run");
while(true) {
try {
System.out.println("sleeping");
Thread.sleep(1000);
}
catch(InterruptedException e) {
System.out.println("catch interrupt");
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Thread t = new Thread(new Factory());
t.start();
try {
Thread.sleep(2000);
}
catch(InterruptedException e) {
System.out.println("main interrupt");
}
System.out.println("main thread excute t interrupt");
t.interrupt();
}
}
output:
begin run
sleeping
sleeping
main thread excute t interrupt
sleeping
catch interrupt
java.lang.InterruptedException: sleep interruptedsleeping
at java.lang.Thread.sleep(Native Method)
at info.Factory.run(Factory.java:11)
at java.lang.Thread.run(Unknown Source)
sleeping
sleeping
sleeping
sleeping
sleeping
sleeping
sleeping
sleeping
sleeping
sleeping
sleeping
sleeping
sleeping
sleeping
sleeping
sleeping
被catch了,只是将这个线程从堵塞状态变为非堵塞状态,并死循环
如果将代码修改为
public void run() {
System.out.println("begin run");
while(!Thread.interrupted()) {
try {
System.out.println("sleeping");
Thread.sleep(2000);
}
catch(InterruptedException e) {
System.out.println("catch interrupt");
System.out.println("thread is interrupted ? " + Thread.interrupted());
e.printStackTrace();
}
}
}output:
begin run
sleeping
sleeping
main thread excute t interrupt
catch interrupt
thread is interrupted ? false
java.lang.InterruptedException: sleep interruptedsleeping
at java.lang.Thread.sleep(Native Method)
at info.Factory.run(Factory.java:11)
at java.lang.Thread.run(Unknown Source)
sleeping
sleeping
sleeping
还是死循环,虽然发生了中断,但是interrupted的中断位还是false,这是因为在抛出异常时候,自动将其设为了false
将代码修改如下,就可以了
public void run() {
System.out.println("begin run");
while(!Thread.interrupted()) {
try {
System.out.println("sleeping");
Thread.sleep(2000);
}
catch(InterruptedException e) {
System.out.println("catch interrupt");
System.out.println("thread is interrupted ? " + Thread.interrupted());
Thread.currentThread().interrupt();
e.printStackTrace();
}
}
} 对于非阻塞中的线程, 只是改变了中断状态, 即Thread.Interrupted()将返回true; 对于可取消的阻塞状态中的线程, 比如等待在这些函数上的线程, Thread.sleep(), Object.wait(), Thread.join(), 这个线程收到中断信号后, 会抛出InterruptedException, 同时会把中断状态置回为false.
public void run() {
System.out.println("begin run");
while(!Thread.interrupted()) {
System.out.println("sleeping");
}
}通用的写法,不论是否是堵塞,应该这样写
public void run() {
System.out.println("begin run");
try {
while(!Thread.interrupted()) {
System.out.println("sleeping");//如果在这句话,就是非堵塞的时候收到中断信号,那么其interrupted变为true,在下次循环判断时就退出
Thread.sleep(2000); //如果在这句话,也就是在堵塞的时候收到中断信号,那么就会抛出一个异常,interrupted在抛出异常时又变为false
}
}
catch(InterruptedException e) {
System.out.println("catch interrupt");
}
}看到一个例子,可以比较好的展现interrupt的机制
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class test {
/**
* @param args
*/
private ReentrantLock lock = new ReentrantLock();
public Runnable createTask() {
return new Runnable() {
public void run() {
while (true) {
try {
lock.lock();
{
//if(lock.tryLock()) {
//if (lock.tryLock(500, TimeUnit.MILLISECONDS)) {
try {
System.out.println("locked "+Thread.currentThread().getName());
System.out.println("begin sleep "+Thread.currentThread().getName());
Thread.sleep(10000);
System.out.println("end sleep "+Thread.currentThread().getName());
}
finally {
lock.unlock();
System.out.println("unlock "+Thread.currentThread().getName());
}
break;
}
// else {
// System.out.println("unable to lock "+Thread.currentThread().getName());
// }
} catch(InterruptedException e) {
System.out.println("interrupted "+Thread.currentThread().getName());
}
}//while
}
};
}
public static void main(String[] args)throws Exception {
test t = new test();
Thread t1 = new Thread(t.createTask(), "T1");
Thread t2 = new Thread(t.createTask(), "T2");
t1.start();
t2.start();
Thread.sleep(600);
t2.interrupt();
}
}
output:
locked T1
begin sleep T1
end sleep T1
unlock T1
locked T2
begin sleep T2
unlock T2
interrupted T2
locked T2
begin sleep T2
end sleep T2
unlock T2
T1线程先得到所,就睡眠了10秒,T2就堵塞了10秒,在这10秒内主线程对T2发出了一个interrupt消息,但是因为T2在等待锁的过程中,是不会响应中断信号的。
10秒之后,T2获得了锁,注意调用线程interrupt的唯一作用就是将线程内部的interruption变量变为了ture,但是一旦线程进入不是因为等待锁而导致的堵塞时,发现这个变量是ture, 这时就产生了一个interruption中断,但是注意这里finally的作用,即使有异常了,但是也得必须运行finally块内部的代码,然后再跳到外层的catch中。
如果调用线程的.isInterrupted()函数,就会显示是否有中断,然后在把中断变量设为false.
如果将16行改为lock.lockInterruptibly(); 就是T2在等待锁的过程中,也会响应中断信号。
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class test {
/**
* @param args
*/
private ReentrantLock lock = new ReentrantLock();
public Runnable createTask() {
return new Runnable() {
public void run() {
while (true) {
try {
//lock.lockInterruptibly();
//{
//if(lock.tryLock()) {
if (lock.tryLock(5000, TimeUnit.MILLISECONDS)) {
try {
System.out.println("locked "+Thread.currentThread().getName());
System.out.println("begin sleep "+Thread.currentThread().getName());
Thread.sleep(10000);
System.out.println("end sleep "+Thread.currentThread().getName());
}
finally {
lock.unlock();
System.out.println("unlock "+Thread.currentThread().getName());
}
break;
}
else {
System.out.println("unable to lock "+Thread.currentThread().getName());
}
} catch(InterruptedException e) {
System.out.println("interrupted "+Thread.currentThread().getName());
}
}//while
}
};
}
public static void main(String[] args)throws Exception {
test t = new test();
Thread t1 = new Thread(t.createTask(), "T1");
Thread t2 = new Thread(t.createTask(), "T2");
t1.start();
Thread.sleep(50);
t2.start();
Thread.sleep(600);
t2.interrupt();
}
}
tryLock在等待锁的时候也会响应中断
看看这个程序有什么问题?
public class SemaphoreTest extends Thread {
Semaphore position;
private int id;
public SemaphoreTest(int i, Semaphore s) {
this.id = i;
this.position = s;
}
public void run() {
try {
if (position.availablePermits() > 0) {
System.out.println("顾客[" + id + "]进入厕所,有空位");
} else {
System.out.println("顾客[" + id + "]进入厕所,没空位,排队");
}
position.acquire();
System.out.println("【" + id + "】acquire坑位");
Thread.sleep((int) (Math.random() * 1000));
System.out.println("【" + id + "】完毕release");
position.release();
}
catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
ExecutorService pool = Executors.newCachedThreadPool();
Semaphore position = new Semaphore(2); // 初始化两个空位
for (int i = 0; i < 5; i++) {
pool.submit(new SemaphoreTest(i, position));
}
System.out.println("开始释放线程池资源");
pool.shutdownNow();
System.out.println("完成释放线程池资源");
position.acquireUninterruptibly(2);
System.out.println("如厕完毕,清理厕所");
position.release(2);
}
}
但是堵塞着的程序并没有finally块来释放semaphore,导致主线程死等
深入理解Java线程中断机制及其实现
1660

被折叠的 条评论
为什么被折叠?



