thread之join

thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。或者说join() 的作用:让“主线程”等待“子线程”结束之后才能继续运行。

方法:

t.join();      //使调用线程 t 在此之前执行完毕。
t.join(1000);  //等待 t 线程,等待时间是1000毫秒

 

public class TestThreadJoin {
  public static void main(String[] args){
     System.out.println("system start time:"+System.currentTimeMillis());
     Thread A = new Thread(){
      @Override
      public void run() {
        try {
            sleep(200);
          } catch (InterruptedException e) {
                 e.printStackTrace();
           }
        for(int i=0;i<10;i++){
           System.out.println("current thread :"+
                        Thread.currentThread().getName());}
           System.out.println("current thread :"+
                                 Thread.currentThread().getName());
          System.out.println("A thread execute end time :"+
                                 System.currentTimeMillis()); }
          };

        Thread B = new Thread(A);
        System.out.println("A name:"+A.getName());
        System.out.println("B name:"+B.getName());
        A.start();
        B.start();
        try {
            System.out.println("current thread in    
                          main:"+Thread.currentThread().getName());
            B.join(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("main end time:"+System.currentTimeMillis());
    }
}

 

system start time:1466060949347
A name:Thread-0
B name:Thread-1
current thread in main:main
main end time:1466060949403
current thread :Thread-1
current thread :Thread-0
current thread :Thread-1
current thread :Thread-0
current thread :Thread-0
current thread :Thread-1
current thread :Thread-0
current thread :Thread-0
current thread :Thread-1
current thread :Thread-0
current thread :Thread-1
current thread :Thread-0
current thread :Thread-1
current thread :Thread-0
current thread :Thread-1
current thread :Thread-0
current thread :Thread-1
current thread :Thread-0
current thread :Thread-1
current thread :Thread-0
current thread :Thread-1
current thread :Thread-1
A thread execute end time :1466060949553
A thread execute end time :1466060949553

 

先上一段JDK中代码:

  /**
     * Waits at most {@code millis} milliseconds for this thread to
     * die. A timeout of {@code 0} means to wait forever.
     * <p> This implementation uses a loop of {@code this.wait} calls
     * conditioned on {@code this.isAlive}. As a thread terminates the
     * {@code this.notifyAll} method is invoked. It is recommended that
     * applications not use {@code wait}, {@code notify}, or
     * {@code notifyAll} on {@code Thread} instances.
     * @param  millis
     *         the time to wait in milliseconds
     * @throws  IllegalArgumentException
     *          if the value of {@code millis} is negative
     * @throws  InterruptedException
     *          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() 方法是没有作用的,将直接继续向下执行

Join方法实现是通过wait(小提示:Object 提供的方法)。 当main线程调用t.join时候,main线程会获得线程对象t的锁(wait 意味着拿到该对象的锁),调用该对象的wait(等待时间),直到该对象唤醒main线程 ,比如退出后。这就意味着main 线程调用t.join时,必须能够拿到线程t对象的锁

 

 

class MyThread extends Thread {
     public void run() { 
         System.out.println(getName() + "开始sleep" );
         try {
             Thread.sleep( 2000 );
         } catch (Exception e) {
             e.printStackTrace();
         }
         System.out.println(getName() + "结束sleep" );
     }
}
public class TestWaitNotify { 
     public static void main(String[] args)  
     throws Exception { 
         Thread myThread = new MyThread(); 
         myThread.start();
        
         synchronized (myThread) { 
             myThread.wait(); 
         }
         
         System.out.println( "wait结束." );
     }
}

myThread执行结束后,main线程中的wait操作就自动退出了。程序里也并没有看到有notify/notifyAll调用。 

 如果将程序改成下面这样:

class MyThread extends Thread {
     public void run() { 
         System.out.println(getName() + "开始sleep" );
         try {
             Thread.sleep( 2000 );
         } catch (Exception e) {
             e.printStackTrace();
         }
         System.out.println(getName() + "结束sleep" );
     }
}
public class TestWaitNotify { 
     public static void main(String[] args)  
     throws Exception { 
         Thread myThread = new MyThread(); 
         myThread.start();
         
         Object tmp = new Object();
         synchronized (tmp) { 
             tmp.wait(); 
         }
         
         System.out.println( "wait结束." );
     }
}

wait操作作用在一个独立的对象上,而不是像前面那样作用于线程对象上。这时程序就会一直wait下去。

给人直观的感觉,要么是发生了虚假唤醒,要么是线程在结束的时候做了些事情。经过查找,终于在JDK1.7 API文档的带参数的join方法上发现了蛛丝马迹!它是这么说的:

This implementation uses a loop of this.wait calls conditioned on this.isAlive. As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.

也就是说join的实现方式大概如下:

while ( this .isAlive()) {
     this .wait();
}

当线程结束的时候会调用notifyAll方法来让join方法返回,这个调用也影响了我们的应用程序。这也是为什么wait调用一定要放到一个循环中的因素之一。文档中也写明了不推荐我们的应用在Thread实例上调用wait, notify, or notifyAll。

在JDK1.7之前的API文档中是找不到这些描述的。碰到这样的问题只能去找JVM源码了。且在JDK1.7的文档中,这个信息还是出现在join方法上,调用wait/notify出问题的时候,如果事先不了解这个机制,又怎么会去看join方法的API呢!由此可见,一份好的JAVA DOC文档的重要性。

 

### 线程中 `Join` 方法的作用和使用方式 #### 作用 `Join` 方法在多线程编程中用于实现线程之间的同步,其核心作用是让调用该方法的线程等待目标线程执行完毕后再继续执行。通过这种方式,可以确保某些操作在依赖的线程完成后才进行。 - 在 **Python** 中,`threading` 模块提供了 `join()` 方法,允许主线程等待子线程完成[^5]。 - 在 **C#** 中,`Thread.Join()` 方法可以让主线程等待子线程结束[^2]。 - 在 **Java** 中,`Thread.join()` 方法同样用于主线程等待子线程完成任务[^3]。 #### 使用示例 ##### Python 示例 下面是一个简单的 Python 示例,展示如何使用 `join()` 方法: ```python import threading import time def worker(): print("Worker thread started") time.sleep(2) print("Worker thread finished") # 创建线程 t = threading.Thread(target=worker) t.start() # 主线程等待子线程完成 t.join() print("Main thread continues after worker thread") ``` 在这个例子中,主线程调用了 `t.join()`,因此它会等待 `worker` 线程执行完毕后才会继续打印后续信息[^5]。 ##### C# 示例 以下是一个 C# 的示例,展示了 `Thread.Join()` 的使用: ```csharp using System; using System.Threading; public class Example { static Thread thread1, thread2; public static void Main() { thread1 = new Thread(ThreadProc); thread1.Name = "Thread1"; thread1.Start(); thread2 = new Thread(ThreadProc); thread2.Name = "Thread2"; thread2.Start(); Console.ReadKey(); } private static void ThreadProc() { Console.WriteLine("\nCurrent thread: {0}", Thread.CurrentThread.Name); if (Thread.CurrentThread.Name == "Thread1" && thread2.ThreadState != ThreadState.Unstarted) { Console.WriteLine("thread2.Join"); thread2.Join(); } Thread.Sleep(1000); Console.WriteLine("\nCurrent thread: {0}", Thread.CurrentThread.Name); Console.WriteLine("Thread1: {0}", thread1.ThreadState); Console.WriteLine("Thread2: {0}\n", thread2.ThreadState); } } ``` 在这个示例中,`Thread1` 调用了 `thread2.Join()`,这意味着 `Thread1` 会等待 `Thread2` 完成后才继续执行[^2]。 ##### Java 示例 以下是一个 Java 的示例,展示了 `Thread.join()` 的使用: ```java public class JoinExample { public static void main(String[] args) { Thread thread1 = new Thread(() -> { try { System.out.println("Thread1 is running"); Thread.sleep(2000); // Simulate work System.out.println("Thread1 is finished"); } catch (InterruptedException e) { e.printStackTrace(); } }); Thread thread2 = new Thread(() -> { try { System.out.println("Thread2 is running"); Thread.sleep(1000); // Simulate work System.out.println("Thread2 is finished"); } catch (InterruptedException e) { e.printStackTrace(); } }); thread1.start(); thread2.start(); try { // Wait for both threads to finish thread1.join(); thread2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("All threads have finished execution"); } } ``` 在这个例子中,主线程调用了 `thread1.join()` 和 `thread2.join()`,因此它会等待 `thread1` 和 `thread2` 都完成后才会继续执行[^3]。 #### 注意事项 - 在 Python 中,如果线程的 `daemon` 属性为 `True`,那么 `join(timeout)` 参数是有效的,主线程会在超时时间后结束子线程。需要注意的是,如果有多个子线程调用 `join(timeout)`,主线程实际等待的时间可能是所有超时时间的总和[^5]。 - 在 Java 中,`join()` 方法内部通过检查线程是否存活(`isAlive()`)并调用 `wait(0)` 来实现等待。这里的关键在于 `wait()` 是让当前线程(即主线程)等待,而不是让目标线程等待[^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值