`

Thread--join()

阅读更多
转自http://blog.csdn.net/bzwm/archive/2009/02/12/3881392.aspx



一、在研究join的用法之前,先明确两件事情。

1.join方法定义在Thread类中,则调用者必须是一个线程,

例如:

Thread t = new CustomThread();//这里一般是自定义的线程类

t.start();//线程起动

t.join();//此处会抛出InterruptedException异常



2.上面的两行代码也是在一个线程里面执行的。



以上出现了两个线程,一个是我们自定义的线程类,我们实现了run方法,做一些我们需要的工作;另外一个线程,生成我们自定义线程类的对象,然后执行

customThread.start();

customThread.join();

在这种情况下,两个线程的关系是一个线程由另外一个线程生成并起动,所以我们暂且认为第一个线程叫做“子线程”,另外一个线程叫做“主线程”。



二、为什么要用join()方法

主线程生成并起动了子线程,而子线程里要进行大量的耗时的运算(这里可以借鉴下线程的作用),当主线程处理完其他的事务后,需要用到子线程的处理结果,这个时候就要用到join();方法了。





三、join方法的作用

在网上看到有人说“将两个线程合并”。这样解释我觉得理解起来还更麻烦。不如就借鉴下API里的说法:

“等待该线程终止。”

解释一下,是主线程(我在“一”里已经命名过了)等待子线程的终止。也就是在子线程调用了join()方法后面的代码,只有等到子线程结束了才能执行。(Waits for this thread to die.)





四、用实例来理解

写一个简单的例子来看一下join()的用法,一共三个类:

1.CustomThread 类

2. CustomThread1类

3. JoinTestDemo 类,main方法所在的类。



代码1:

view plaincopy to clipboardprint?
package wxhx.csdn2; 
/**

* @author bzwm
*
*/ 
class CustomThread1 extends Thread { 
    public CustomThread1() { 
        super("[CustomThread1] Thread"); 
    }; 
    public void run() { 
        String threadName = Thread.currentThread().getName(); 
        System.out.println(threadName + " start."); 
        try { 
            for (int i = 0; i < 5; i++) { 
                System.out.println(threadName + " loop at " + i); 
                Thread.sleep(1000); 
            } 
            System.out.println(threadName + " end."); 
        } catch (Exception e) { 
            System.out.println("Exception from " + threadName + ".run"); 
        } 
    } 

class CustomThread extends Thread { 
    CustomThread1 t1; 
    public CustomThread(CustomThread1 t1) { 
        super("[CustomThread] Thread"); 
        this.t1 = t1; 
    } 
    public void run() { 
        String threadName = Thread.currentThread().getName(); 
        System.out.println(threadName + " start."); 
        try { 
            t1.join(); 
            System.out.println(threadName + " end."); 
        } catch (Exception e) { 
            System.out.println("Exception from " + threadName + ".run"); 
        } 
    } 

public class JoinTestDemo { 
    public static void main(String[] args) { 
        String threadName = Thread.currentThread().getName(); 
        System.out.println(threadName + " start."); 
        CustomThread1 t1 = new CustomThread1(); 
        CustomThread t = new CustomThread(t1); 
        try { 
            t1.start(); 
            Thread.sleep(2000); 
            t.start(); 
            t.join();//在代碼2里,將此處注釋掉 
        } catch (Exception e) { 
            System.out.println("Exception from main"); 
        } 
        System.out.println(threadName + " end!"); 
    } 




打印结果:



main start.//main方法所在的线程起动,但没有马上结束,因为调用t.join();,所以要等到t结束了,此线程才能向下执行。

[CustomThread1] Thread start.//线程CustomThread1起动

[CustomThread1] Thread loop at 0//线程CustomThread1执行

[CustomThread1] Thread loop at 1//线程CustomThread1执行

[CustomThread] Thread start.//线程CustomThread起动,但没有马上结束,因为调用t1.join();,所以要等到t1结束了,此线程才能向下执行。

[CustomThread1] Thread loop at 2//线程CustomThread1继续执行

[CustomThread1] Thread loop at 3//线程CustomThread1继续执行

[CustomThread1] Thread loop at 4//线程CustomThread1继续执行

[CustomThread1] Thread end. //线程CustomThread1结束了

[CustomThread] Thread end.// 线程CustomThread在t1.join();阻塞处起动,向下继续执行的结果

main end!//线程CustomThread结束,此线程在t.join();阻塞处起动,向下继续执行的结果。



修改一下代码,得到代码2:(这里只写出修改的部分)

view plaincopy to clipboardprint?
public class JoinTestDemo { 
    public static void main(String[] args) { 
        String threadName = Thread.currentThread().getName(); 
        System.out.println(threadName + " start."); 
        CustomThread1 t1 = new CustomThread1(); 
        CustomThread t = new CustomThread(t1); 
        try { 
            t1.start(); 
            Thread.sleep(2000); 
            t.start(); 
//          t.join();//在代碼2里,將此處注釋掉 
        } catch (Exception e) { 
            System.out.println("Exception from main"); 
        } 
        System.out.println(threadName + " end!"); 
    } 




打印结果:



main start. // main方法所在的线程起动,但没有马上结束,这里并不是因为join方法,而是因为Thread.sleep(2000);

[CustomThread1] Thread start. //线程CustomThread1起动

[CustomThread1] Thread loop at 0//线程CustomThread1执行

[CustomThread1] Thread loop at 1//线程CustomThread1执行

main end!// Thread.sleep(2000);结束,虽然在线程CustomThread执行了t1.join();,但这并不会影响到其他线程(这里main方法所在的线程)。

[CustomThread] Thread start. //线程CustomThread起动,但没有马上结束,因为调用t1.join();,所以要等到t1结束了,此线程才能向下执行。

[CustomThread1] Thread loop at 2//线程CustomThread1继续执行

[CustomThread1] Thread loop at 3//线程CustomThread1继续执行

[CustomThread1] Thread loop at 4//线程CustomThread1继续执行

[CustomThread1] Thread end. //线程CustomThread1结束了

[CustomThread] Thread end. // 线程CustomThread在t1.join();阻塞处起动,向下继续执行的结果





五、从源码看join()方法



在CustomThread的run方法里,执行了t1.join();,进入看一下它的JDK源码:

view plaincopy to clipboardprint?
public final void join() throws InterruptedException { 
n(0); 


然后进入join(0)方法:



view plaincopy to clipboardprint?
   /**
    * Waits at most <code>millis</code> milliseconds for this thread to 
    * die. A timeout of <code>0</code> means to wait forever. //注意这句
    *
    * @param      millis   the time to wait in milliseconds.
    * @exception  InterruptedException if another 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) //参数millis为0. 
   throws InterruptedException { 
long base = System.currentTimeMillis(); 
long now = 0; 
if (millis < 0) { 
           throw new IllegalArgumentException("timeout value is negative"); 

if (millis == 0) {//进入这个分支 
    while (isAlive()) {//判断本线程是否为活动的。这里的本线程就是t1. 
    wait(0);//阻塞 
    } 
} else { 
    while (isAlive()) { 
    long delay = millis - now; 
    if (delay <= 0) { 
        break; 
    } 
    wait(delay); 
    now = System.currentTimeMillis() - base; 
    } 

   } 







单纯从代码上看,如果线程被生成了,但还未被起动,调用它的join()方法是没有作用的。将直接继续向下执行,这里就不写代码验证了。
分享到:
评论

相关推荐

    关于C#中Thread.Join()的一点理解

    是第一次在C#中接触Thread,自己研究了一下其中Thread.Join()这个方法,下面谈谈自己的理解。  Thread.Join()在MSDN中的解释很模糊:Blocks the calling thread until a thread terminates  有两个主要问题: ...

    thread-multi.zip

    使用`join()`方法可以让一个线程等待另一个线程完成;`Interrupt()`用于中断线程;`Thread.yield()`让当前线程暂停,让其他线程有机会运行。 6. **线程优先级**: Java线程有优先级,通过`setPriority()`方法可以...

    JAVA CountDownLatch与thread-join()的区别解析

    JAVA CountDownLatch与thread-join()的区别解析 JAVA 中的线程同步机制是非常重要的,CountDownLatch 和 thread-join() 是两种常用的线程同步方法,本文将详细介绍它们之间的区别。 首先, thread-join() 方法是...

    Thread-and-Process-Source-code.rar_Process Thread

    2. `std::thread`类提供了创建、同步和销毁线程的功能,例如`std::thread::join()`用于等待线程完成,`std::thread::detach()`则允许线程独立运行。 3. Windows API中的`CreateThread`函数创建一个新的线程,需要...

    java-multi-thread-mechanism.rar_java thread ppt

    - `join()`: 等待当前线程结束再执行后续代码。 - `sleep()`: 让当前线程休眠一段时间。 - `interrupt()`: 中断线程,如果线程在阻塞状态,会抛出`InterruptedException`。 5. **线程同步** - `synchronized`...

    java-thread-vedio.rar_java vedio

    这个"java-thread-vedio.rar_java vedio"压缩包文件显然包含了关于Java多线程的视频教程,适合初学者或者需要深化理解多线程的开发者学习。下面我们将详细探讨Java线程的相关知识点。 1. **线程的创建方式**: - *...

    线程创建,线程等待与清除,thread_clean.c,thread_create.c,thread_create.c,thread_exit_struct.c,thread_id.c,thread_int.c, thread_join.c, thread_join.c, thread_string.c, thread_struct.c

    线程等待通常指的是一个线程(父线程)等待另一个线程(子线程)完成其工作,这通常通过`pthread_join()`函数实现,如`thread_join.c`所示。`pthread_join()`让调用线程阻塞,直到指定的线程结束。线程清除,或线程...

    kill-Thread-using-MySQL-connection.rar_Because..._mysql thread

    2. **优化SQL**:对查询进行优化,避免全表扫描,使用索引,减少JOIN操作等。 3. **设置超时**:合理配置`MySQL`的`wait_timeout`和`interactive_timeout`参数,以防止线程因长时间无响应而被自动断开。 4. **事务...

    CountDownLatch与thread.join()的区别

    CountDownLatch与thread.join()的区别

    c++11中关于std::thread的join的详解

    C++11中关于std::thread的join详解 C++11引入了std::thread库,提供了对多线程编程的支持。std::thread库提供了两个基本操作:join和detach。join操作用于回收线程资源,避免资源泄露;detach操作用于将线程与创建...

    java-Thread-study-summary.zip_java 多线程

    - 守护(Timed Waiting):线程调用了带有超时参数的`wait()`、`sleep()`或`join()`,等待一段时间后自动唤醒。 - 结束(Terminated):`run()`方法执行完毕,线程结束。 3. **线程同步** - `synchronized`...

    C#多线程之Thread中Thread.Join()函数用法分析

    本文实例讲述了C#多线程之Thread中Thread.Join()函数用法。分享给大家供大家参考。具体分析如下: Thread.Join()在MSDN中的解释:Blocks the calling thread until a thread terminates 当NewThread调用Join方法的...

    the-application-of-the-Thread-class.rar_The Class

    在Java编程语言中,`Thread`类是处理并发执行的核心组件。这个类允许开发者创建和管理线程,从而实现多任务并行运行。本讲座主要聚焦于`Thread`类的应用,探讨如何有效地利用线程来提升程序的效率和响应性。 一、...

    thread-stream:一种将数据发送到Node.js辅助线程的流传输方式

    npm i thread-stream 用法 'use strict' const ThreadStream = require ( 'thread-stream' ) const { join } = require ( 'path' ) const stream = new ThreadStream ( { filename : join ( __dirname , 'worker.js...

    boost的Thread.lib(VC 6.0++)

    5. **线程Join和Detach**:`join`方法使调用线程等待指定线程结束,而`detach`则将线程与调用线程分离,让其独立运行。 6. **线程组管理**:`boost::thread_group`类可以管理一组线程,方便地启动、停止和等待所有...

    thread-sanitizer.md

    # 利用Thread Sanitizer工具检查数据竞争的问题 ## 例子 #include int Global; void *Thread1(void *x) { Global = 42; return x;... pthread_create(&t, NULL... pthread_join(t, NULL); return Global; }

    the-design-of-thread-pool-on-Linux.rar_thread pool_并发 线程池

    线程池在Linux环境下的设计是一项关键...《the design of thread pool on Linux.doc》这份文档很可能详细介绍了线程池的设计思路、实现细节以及在实际项目中的应用案例,对于深入理解和使用线程池具有很高的参考价值。

    q-thread-pool:一个非常简单的基于JPL-QUEUES的线程池实现

    (join-thread-pool *thread-pool*) ;; 关闭线程池 (stop-thread-pool *thread-pool*) ``` 五、总结 q-thread-pool是Common Lisp环境下实现线程池的一个优秀选择,它的设计简洁且高效,利用JPL-QUEUES提供的队列...

    Linux-thread-pool.rar_线程池

    - 销毁线程:当线程不再需要时,使用`pthread_join`等待线程结束,然后释放资源。 - 任务队列:可以使用`std::queue`配合互斥锁和条件变量实现一个简单的并发安全队列。 4. **性能优化** - **线程池大小**:合适...

    Java中Thread.join()的使用方法

    Java 中 Thread.join() 的使用方法 Thread.join() 是 Java 中的一个重要方法,该方法允许一个线程等待另一个线程的执行完成。下面我们将详细介绍 Thread.join() 的使用方法、源码分析和示例代码。 1. join() 的...

Global site tag (gtag.js) - Google Analytics