Java中join()方法的理解
thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。
比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。
t.join(); //调用join方法,等待线程t执行完毕
t.join(1000); //等待 t 线程,等待时间是1000毫秒。
下面是一段JDK中的代码:
/** * Waits at most <code>millis</code> milliseconds for this thread to * die. A timeout of <code>0</code> means to wait forever. */ 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) { while (isAlive()) { wait(0); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base; } } }
从代码上看,如果线程被生成了,但还未被起动,调用它的 join() 方法是没有作用的,将直接继续向下执行
Join方法实现是通过wait(小提示:Object 提供的方法)。 当main线程调用t.join时候,main线程会获得线程对象t的锁(wait 意味着拿到该对象的锁),调用该对象的wait(等待时间),直到该对象唤醒main线程 ,比如退出后。这就意味着main 线程调用t.join时,必须能够拿到线程t对象的锁。
通过下面一段代码解释:
package ThreadTest; import static java.lang.Thread.currentThread; import static java.lang.Thread.sleep; /** * Created with IntelliJ IDEA. * User: Blank * Date: 14-3-28 * Time: 下午7:49 */ public class TestJoin implements Runnable { public static void main(String[] sure) throws InterruptedException { Thread t = new Thread(new TestJoin()); long start = System.currentTimeMillis(); t.start(); t.join(1000);//等待线程t 1000毫秒 System.out.println(System.currentTimeMillis()-start);//打印出时间间隔 System.out.println("Main finished");//打印主线程结束 } @Override public void run() { // synchronized (currentThread()) { for (int i = 1; i <= 5; i++) { try { sleep(1000);//睡眠5秒,循环是为了方便输出信息 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("睡眠" + i); } System.out.println("TestJoin finished");//t线程结束 } //} }
在注释掉synchronized修饰的run方法后,打印信息如下:
可以看到main线程等待了t线程1000毫秒之后,结束了,随后是t线程打印的数据。
那么如果加上run方法的synchronized那条语句呢?结果如下:
由于先调用了t.start()方法,线程进入synchronized代码段,main线程等待一秒以后,还是得不到线程t的对象锁,只能继续等待,直到线程t结束,释放锁。这里可以明确看到main线程等待时间是5000ms,有些文章里写的是t线程执行时间+join方法指定的时间(5000+1000 ),其实不是的,这里可以很清晰的看到,main线程等待时间只有5000ms,看到有的文章说join调用的wait也是需要获取对象锁的。
JDK源代码中wait操作是
public final native void wait(long timeout) throws InterruptedException;
wait内部实现应该是用synchronized,等待时间是5000+1000就好解释了,搞不明白。
此处存疑。