Java中的线程连接指南

98 阅读5分钟

在本教程中,我们将学习**如何连接两个线程以及为什么需要在Java中连接线程。**我们将详细探讨 ***Thread.join()***API和不同版本的API,并结合实际例子。

我们还将看到,在使用线程时,我们是如何陷入死锁状态的。 *join()*以及在我们的代码中有效使用它的方法。

目录

  1. 1.线程连接的介绍
  2. 2.Java Thread.join() API
  3. 3.中断一个连接的线程
  4. 4.注意死锁
  5. 5.总结

1.线程连接的介绍

线程 是一个轻量级的进程,它允许一个程序通过并行运行多个线程来更有效地运行。如果我们有一个要求,即第一个线程 必须等待第二个线程完成其执行,那么我们应该连接这两个线程。

让我们举个例子来更清楚地了解它。假设我们有3个线程,为一个婚姻应用程序执行3种不同的活动。

  • 一旦婚礼卡打印活动完成,婚礼卡分发活动就开始,一旦我们确定了婚礼的地点,婚礼卡打印活动就开始。
  • 我们可以说,在这种情况下,Thread-3必须等待Thread-2完成,而且Thread-2也必须等待Thread-1完成其执行。
  • 线程-2必须调用Thread-1.join(),而线程-3必须调用Thread-2.join() ,这样他们就会等到另一个线程的完成。

2.JavaThread.join() API

join()方法使调用的Thread进入等待状态,直到被调用join()Thread完成其执行。

  • 一个线程 't1' ,想要等到另一个线程 't2' ,完成它的执行,那么t1必须调用t2的*join()*方法。
  • *t2.join()*由t1调用。
  • 当t1执行t2.join()时,t1立即进入等待状态并继续等待,直到t2完成其执行并终止。
  • 一旦t2完成了,那么只有t1继续执行它。

thread join

连接线程的生命周期

2.1 无超时的连接

默认的join()方法会让当前的线程无限期地等待,直到它所调用的线程完成。如果该线程被打断,它将抛出*InterruptedException。*

public final void join() throws InterruptedException

现在让我们来看看一个如何使用*join()* 方法的例子。

public class ChildThread extends Thread
{  
         public void run()
         {  
              for(int i=1; i<=4; i++)
              {  
                 try{  
                         Thread.sleep(500);  
                      } catch(Exception e){
                          System.out.println(e);
                      }
                 System.out.println(“child thread execution - ” + i);  
              }  
         }  
}
ChildThread th1 = new ChildThread();

// Starting child Thread
th1.start();

// main thread joining the child thread
th1.join();

// main Thread printing statements
System.out.println(“main thread completed”);

注意程序的输出。主线程正在调用子线程的*join()*方法并等待其完成,所以在调用*join()*之后。所以,子线程的所有语句都在主线程语句之前打印。

child thread execution - 1
child thread execution - 2
child thread execution - 3
child thread execution – 4
main thread completed

2.2 带超时的连接

  • join(long millis): 它使当前线程 等待,直到它所调用的线程 完成,或者指定的时间(以毫秒为单位)已经过期。
  • join(long millis, int nanos): 它让当前的Thread等待,直到它被调用的Thread完成,或者指定的时间(毫秒+纳秒)已经过期。
public final synchronized void join(long millis) throws InterruptedException

public final synchronized void join(long millis, int nanos) throws InterruptedException

现在让我们通过一个例子来看看它是如何工作的。

// Creating child Thread Object
ChildThread th1 = new ChildThread();
// Starting child Thread
th1.start();

//main thread joining the child thread with 1000ms expiration time
th1.join(1000);

// main Thread printing statements
System.out.println(“main thread completed”);

当程序执行时,主线程最多会等待1000ms,之后会随时被调用。

child thread execution - 1
main thread completed
child thread execution - 2
child thread execution - 3
child thread execution - 4

3.中断一个已加入的线程

一个等待的线程 可以被另一个线程使用interrupt() 方法打断。 一旦等待中的Thread被中断,它就会立即从等待状态中出来 ,进入Ready/Runnable状态,并等待Thread Scheduler分配处理器以再次开始执行。

// Creating child Thread by extending Thread class
public class ThreadjoiningInterrupt extends Thread 
{
     // main Thread reference
	private static Thread mt;

    // Job of child Thread
	public void run() 
        {
		for (int i = 1; i <= 4; i++) {

                    // child Thread interrupting main Thread
			mt.interrupt();

                    // child Thread prints statements
			System.out.println("Child Thread Execution - " + i);
		}
	}

    // main Thread Job
	public static void main(String[] args) 
        {
            // Setting main Thread object in 'mt' reference
		Demo.mt = Thread.currentThread();

            // Instantiating child Thread
		Demo t1 = new Demo();

            // Starting child Thread
		t1.start();

		try {
                    // main Thread calls join() on child Thread
			t1.join();
		} catch (InterruptedException ie) {
                     // catching Interrupted Exception
			System.out.println("main Thread is interrupted");
		}

            // main Thread prints statements
		for (int i = 1; i <= 4; i++) {
			System.out.println("main Thread Execution - " + i);
		}
	}
}

注意程序的输出,一旦子线程中断了主线程,那么两个线程就同时执行了。

Child Thread Execution - 1
main Thread is interrupted
Child Thread Execution - 2
main Thread Execution - 1
main Thread Execution - 2
main Thread Execution - 3
main Thread Execution - 4
Child Thread Execution - 3
Child Thread Execution – 4

4.注意死锁

在使用join()方法时,我们必须小心,因为有时它可能导致死锁 的情况。如果**两个线程互相调用join()方法,那么这两个线程就会进入等待状态,永远等待对方

同样地,如果一个线程由于错误地加入了自己,那么它将永远被阻塞,JVM将被关闭以恢复。

class Threadjoindemo
{
public static void main(String[] args)
{
    // main thread calling join() on itself
    Thread.currentThread().join();                     // Program gets stuck, Deadlock suitation
}
}

5.总结

在本教程中,我们已经了解了加入两个线程的必要性以及如何使用 Thread.join() API,无论是否有过期时间。我们还看到了如何中断一个连接的线程。我们还学习了如何处理死锁情况,同时使用*join()*.

学习愉快!!

这个帖子对你有帮助吗?

如果你喜欢这篇文章,请告诉我们。这是我们能够改进的唯一方法。

没有

相关帖子。

  1. 使用java.util.concurrent.ThreadFactory创建线程
  2. 使用UncaughtExceptionHandler重启线程
  3. Java虚拟线程--Project Loom
  4. Java中的AtomicInteger指南
  5. Java中的ExecutorService指南
  6. Java - 等待运行线程结束