一、线程的创建Thread和Runnable两者的优劣思考
在JDK中Thread本身实现了Runnable接口,所以使用实现Runnable接口应该是java最提倡的方式,Runnable和Thread分开使用的好处之一就是就java只支持单继承,如果使用了继承Thread就不能继承其他的类了;其二开发人员无需纠结Thread和Runnable之间的同步块和同步方法之间的内部交互,这种分隔使得对操作的本身与其运行的上下文有着独立的控制。其三,同一个Runnabled对象可以用来初始化其他的线程,也可以用于构造一些轻量级的执行框架(Excutors)。
图1. JDK Thread 继承图
二、interrupt理解
interrupt()方法不会中断或者终止任何线程。interrupt仅仅是设置一个中断标志,当线程处于wait、sleep、join阻塞时,调用interrupt将抛出InterruptedException异常,JVM会自动清除中断标志(改为false)。利用这一特性可以在捕获到InterruptedException异常的时候,将线程的数据共享进行恢复,以安全停止线程。当线程没有进行阻塞时,调用interrupt方法只是将中断标志设置为true,当线程再次被阻塞的时候,抛出InterruptedException,并清除中断标志(设置为false)。interrupt()方法源码如下:
public void interrupt()
{
if (this != Thread.currentThread())
checkAccess();
synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
interrupt0(); // 仅设置一个中断标志 b.interrupt(this); return;
}
}
interrupt0();
}
isInterrupted()方法只是返回当前线程是否被中断,如果中断则返回true,否则返回false。此方法在任何情况下都不会修改线程的中断标志。isInterrupted()方法源码如下:
public boolean isInterrupted()
{
return isInterrupted(false);
}
//参数说明 是否清除中断标志
private native boolean isInterrupted(boolean ClearInterrupted);
Thread.interrupted()静态方法返回当前线程的中断状态,并清除中断状态。(一个线程的中断状态是不允许被其他线程清除的) interrupted() 方法源码如下:
public static boolean interrupted() { return currentThread().isInterrupted(true); }
但是如果调用了Thread.interrupted方法且中断标识还没有被重置,或者是线程处于wait,sleep,join过程中,调用isInterrupted方法将会抛出InterruptedException异常
二、join理解
调用t.join()方法将会暂停执行调用线程(可能是主线程,或者其他线程),直到t线程执行完毕,当调用t.isAlive()返回false时,调用t.join()将直接返回(没有任何意义),所以调用一个没有启动的线程的join()方法也没有任何意义。调用带毫秒数的join(long millis)方法,主线程或者其他线程只会等待millis毫秒,然后又能继续向下继续执行。
public final void join() throws InterruptedException
{
//当相应调用下面的方法 join(0);
}
public final synchronized void join(long millis) throws InterruptedException
{ long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) { throw new IllegalArgumentException("timeout value is negative");}
if (millis == 0) {
//当参数为0时,将一直等待,直到isAlive返回false
while (isAlive()) { wait(0); }
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) { break; }
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
参考:http://ifeve.com/java-concurrency-constructs/
JDK 源码