关于interrupt()
表面上看中断就是让目标线程停止执行的意思,实际上并非完全如此。
严格上讲,线程中断并不会使线程立即退出,而是给线程发送一个通知,告知目标线程有人希望你退出,至于目标线程接到通知后如何处理,则完全由目标线程自行决定。
interrupt()方法的作用实际上是:在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞状态。换句话说,没有被阻塞的线程,调用interrupt()方法是不起作用的。
关于线程的3个重要方法:
interrupt():通知目标线程中断,设置中断标志位。中断标志位表示当前线程已经被中断了。
isInterrupted():判断当前线程是否被中断(通过检查中断标志位)。
interrupted():判断当前中断状态,但同时清除了当前线程的中断标志位状态。
如果希望某线程在中断后退出,就必须为它增加响应的中断处理代码。
如下:
public class Main {
public static void main(String[] args) throws Exception {
Thread t1 = new Thread() {
@Override
public void run() {
while (true) {
System.out.println("run...");
if (Thread.currentThread().isInterrupted()) {
System.out.println("interruptd...");
break;
}
Thread.yield();
}
}
};
t1.start();
Thread.sleep(2000);
t1.interrupt();
}
}
关于yield()
让当前线程让出CPU(并不代表当前线程不执行了),让出CPU后还会进行CPU资源的争夺,但是是否能够再次被分配到,就不一定了。
如果觉得某个线程不是那么重要,或者优先级非常低,有害怕它会占用太多的CPU资源,那么可以在适当的时候调用此方法,给予其他重要线程更多的工作机会。
关于join()
join用于让当前执行线程等待join线程执行结束。其实现原理是不停检查join线程是否存活,如果join线程存活则让当前线程永远wait,代码片段如下,wait(0)表示永远等待下去。
while(isAlive()){
wait(0);
}
直到join线程中止后,线程的this.notifyAll会被调用,调用notifyAll是在JVM里实现的,所以JDK里看不到,有兴趣的同学可以看看JVM源码。JDK不推荐在线程实例上使用wait,notify和notifyAll方法。(参考:http://ifeve.com/talk-concurrency-countdownlatch/)可以用CountDownLatch异步转同步操作。
与sleep的区别:sleep(2000)不释放锁,join(2000)释放锁,因为join()方法内部使用的是wait(),因此会释放锁。