深入浅出Java多线程(1)-方法 join

本系列文章导航

深入浅出Java多线程(1)-方法 join

深入浅出Java多线程(2)-Swing中的EDT(事件分发线程)

深入浅出多线程(3)-Future异步模式以及在JDK1.5Concurrent包中的实现

深入浅出多线程(4)对CachedThreadPool OutOfMemoryError难题的一些想法

深入浅出多线程(5)以并行包线程池为例说说线程池的设计需求及使用

深入浅出多线程(6)分析并行包线程池的设计与实现

 

  对于Java开发人员,多线程应该是必须熟练应用的知识点,特别是开发基于Java语言的产品。本文将深入浅出的表述Java多线程的知识点,在后续的系列里将侧重于Java5由Doug Lea教授提供的Concurrent并行包的设计思想以及具体实现与应用。

  如何才能深入浅出呢,我的理解是带着问题,而不是泛泛的看。所以该系列基本以解决问题为主,当然我也非常希望读者能够提出更好的解决问题的方案以及提出更多的问题。由于水平有限,如果有什么错误之处,请大家提出,共同讨论,总之,我希望通过该系列我们能够深入理解Java多线程来解决我们实际开发的问题。

  作为开发人员,我想没有必要讨论多线程的基础知识,比如什么是线程? 如何创建等 ,这些知识点是可以通过书本和Google获得的。本系列主要是如何理深入解多线程来帮助我们平时的开发,比如线程池如何实现? 如何应用锁等。 

  (1)方法Join是干啥用的? 简单回答,同步,如何同步? 怎么实现的? 下面将逐个回答。

  自从接触Java多线程,一直对Join理解不了。JDK是这样说的:

  join
  public final void join(long millis)throws InterruptedException
  Waits at most millis milliseconds for this thread to die. A timeout of 0 means to wait forever.

  大家能理解吗? 字面意思是等待一段时间直到这个线程死亡,我的疑问是那个线程,是它本身的线程还是调用它的线程的,上代码:

package concurrentstudy; /** * @author vma */ public class JoinTest { public static void main(String[] args) { Thread t = new Thread(new RunnableImpl()); t.start(); try { t.join(1000); System.out.println("joinFinish"); } catch (InterruptedException e) { e.printStackTrace(); } } } class RunnableImpl implements Runnable { public void run() { try { System.out.println("Begin sleep"); Thread.sleep(800); System.out.println("End sleep"); } catch (InterruptedException e) { e.printStackTrace(); } } }

 

  结果是:
Begin sleep
End sleep
joinFinish

  明白了吧,当main线程调用t.join时,main线程等待t线程,等待时间是1000,如果t线程Sleep 2000呢

public void run() { try { System.out.println("Begin sleep"); Thread.sleep(2000); System.out.println("End sleep"); } catch (InterruptedException e) { e.printStackTrace(); } }

  结果是:

Begin sleep
joinFinish
End sleep

 

  也就是说main线程只等1000毫秒,不管T什么时候结束,如果是t.join()呢, 看代码: 

public final void join() throws InterruptedException {
  join(0);
  }

  就是说如果是t.join() = t.join(0) 0 JDK这样说的 A timeout of 0 means to wait forever 字面意思是永远等待,是这样吗?

  其实是等到t结束后。

  这个是怎么实现的吗? 看JDK代码:

  /** * Waits at most <code>millis</code> milliseconds for this thread to die. * A timeout of <code>0</code> means to wait forever. * * @parammillis the time to wait in milliseconds. * @exceptionInterruptedException if any thread has interrupted the current thread.The <i>interrupted status</i> of the current thread is cleared when this exception is thrown. */ 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方法实现是通过wait(小提示:Object 提供的方法)。 当main线程调用t.join时候,main线程会获得线程对象t的锁(wait 意味着拿到该对象的锁),调用该对象的wait(等待时间),直到该对象唤醒main线程,比如退出后。

  这就意味着main 线程调用t.join时,必须能够拿到线程t对象的锁,如果拿不到它是无法wait的,刚开的例子t.join(800)不是说明了main线程等待800毫秒,如果在它等待之前,其他线程获取了t对象的锁,它等待时间可不就是800毫秒了。上代码介绍:

/* * To change this template, choose Tools | Templates and open the template in the editor. */ package concurrentstudy; /** * @author vma */ public class JoinTest { public static void main(String[] args) { Thread t = new Thread(new RunnableImpl()); new ThreadTest(t).start(); t.start(); try { t.join(); System.out.println("joinFinish"); } catch (InterruptedException e) { e.printStackTrace(); } } } class ThreadTest extends Thread { Thread thread; public ThreadTest(Thread thread) { this.thread = thread; } @Override public void run() { holdThreadLock(); } public void holdThreadLock() { synchronized (thread) { System.out.println("getObjectLock"); try { Thread.sleep(9000); } catch (InterruptedException ex) { ex.printStackTrace(); } System.out.println("ReleaseObjectLock"); } } } class RunnableImpl implements Runnable { public void run() { try { System.out.println("Begin sleep"); Thread.sleep(2000); System.out.println("End sleep"); } catch (InterruptedException e) { e.printStackTrace(); } } }

 

  在main方法中 通过new ThreadTest(t).start();实例化ThreadTest 线程对象, 它在holdThreadLock()方法中,通过 synchronized (thread),获取线程对象t的锁,并Sleep(9000)后释放,这就意味着,即使

  main方法t.join(1000),等待一秒钟,它必须等待ThreadTest 线程释放t锁后才能进入wait方法中,它实际等待时间是9000+1000 MS

  运行结果是:

getObjectLock
Begin sleep
End sleep
ReleaseObjectLock
joinFinish

  小结:

  本节主要深入浅出join及JDK中的实现。

 

博文来源:http://www.cqzol.com/programming/Java/200812/198648.html

你可能感兴趣的:(java,JOIN,thread,多线程,Class)