Javamultithreading概念和join()方法

我在Java中的Threads中使用join()方法时感到困惑。 在下面的代码中:

 // Using join() to wait for threads to finish. class NewThread implements Runnable { String name; // name of thread Thread t; NewThread(String threadname) { name = threadname; t = new Thread(this, name); System.out.println("New thread: " + t); t.start(); // Start the thread } // This is the entry point for thread. public void run() { try { for (int i = 5; i > 0; i--) { System.out.println(name + ": " + i); Thread.sleep(1000); } } catch (InterruptedException e) { System.out.println(name + " interrupted."); } System.out.println(name + " exiting."); } } class DemoJoin { public static void main(String args[]) { NewThread ob1 = new NewThread("One"); NewThread ob2 = new NewThread("Two"); NewThread ob3 = new NewThread("Three"); System.out.println("Thread One is alive: " + ob1.t.isAlive()); System.out.println("Thread Two is alive: " + ob2.t.isAlive()); System.out.println("Thread Three is alive: " + ob3.t.isAlive()); // wait for threads to finish try { System.out.println("Waiting for threads to finish."); ob1.t.join(); ob2.t.join(); ob3.t.join(); } catch (InterruptedException e) { System.out.println("Main thread Interrupted"); } System.out.println("Thread One is alive: " + ob1.t.isAlive()); System.out.println("Thread Two is alive: " + ob2.t.isAlive()); System.out.println("Thread Three is alive: " + ob3.t.isAlive()); System.out.println("Main thread exiting."); } } 

这个程序的输出示例如下所示:

 New thread: Thread[One,5,main] New thread: Thread[Two,5,main] New thread: Thread[Three,5,main] Thread One is alive: true Thread Two is alive: true Thread Three is alive: true Waiting for threads to finish. One: 5 Two: 5 Three: 5 One: 4 Two: 4 Three: 4 One: 3 Two: 3 Three: 3 One: 2 Two: 2 Three: 2 One: 1 Two: 1 Three: 1 Two exiting. Three exiting. One exiting. Thread One is alive: false Thread Two is alive: false Thread Three is alive: false Main thread Exiting 

在上面的代码中:

  1. 我不能理解程序的执行stream程,而当ob1被创build时,构造函数被调用,其中t.start()被写入,但仍然run()方法,而main()方法继续执行。 那为什么会这样呢?

  2. join()方法用于等待被调用的线程不终止,但是在这里的输出中,我们看到线程的交替输出为什么?

而如果使用join ,那么这是什么使用synchronized

我知道我在这里错过了一个基本的概念,但我无法弄清楚,所以请帮助。

你必须明白,线程调度是由线程调度器来控制的,所以在一般情况下你不能保证线程执行的顺序。

但是,您可以使用join()等待线程完成其工作。

例如,在你的情况

 ob1.t.join(); 

这个语句直到线程t完成运行才会返回。

尝试这个,

 class Demo { Thread t = new Thread( new Runnable() { public void run () { //do something } } ); Thread t1 = new Thread( new Runnable() { public void run () { //do something } } ); t.start(); // Line 15 t.join(); // Line 16 t1.start(); } 

在上面的例子中,你的主线程正在执行。 当它遇到第15行时,线程调度程序可以使用线程t。 一旦主线程到达第16行,它将等待线程t完成。

注意, t.join没有为线程t或线程t1做任何事情。 它只影响调用它的线程(即main()线程)。

首先,当你创buildob1构造函数被调用并开始执行。 那时t.start()也在单独的线程中运行。 记住当一个新的线程被创build时,它会并行地运行到主线程。 这就是为什么主要开始执行下一个语句。

Join()语句用于防止子线程成为孤立的。 意思是如果你没有在你的主类中调用join() ,那么主线程在执行后会退出,子线程仍然会在那里执行语句。 Join()将等到所有子线程完成其执行,然后只有main方法将退出。

通过这篇文章,帮助很多。

我不能理解程序的执行stream程,而当ob1被创build时,构造函数被调用,其中t.start()被写入,但仍然执行run()方法,而main()方法继续执行。 那为什么会这样呢?

这取决于线程调度程序作为主要共享相同的优先顺序。 调用start()并不意味着run()会立即被调用,它依赖于线程调度器,当它select运行你的线程。

join()方法用于等待被调用的线程不终止,但是在这里的输出中,我们看到线程的交替输出为什么?

这是因为代码中的Thread.sleep(1000)。 删除该行,您将在ob2之前看到ob1完成,然后在ob3之前完成(如使用join()所预期的那样)。 说了这一切都取决于ob1 ob2和ob3何时开始。 调用睡眠会暂停线程执行时间大于1秒(在您的代码中),从而使调度程序有机会调用等待的其他线程(相同的优先级)。

线程的第一条规则 – “线程很有趣”…

我不能理解程序的执行stream程,而当ob1被创build时,构造函数被调用,其中t.start()被写入,但仍然run()方法,而main()方法继续执行。 那为什么会这样呢?

这正是应该发生的事情。 当你调用Thread#start ,线程被创build并安排执行,它可能立即发生(或者足够接近),可能不会。 这涉及到线程调度器。

这涉及到线程执行的安排以及系统中的其他事情。 通常情况下,每个线程在执行“睡眠”之前都会被赋予一定的时间执行,并允许另一个线程执行(显然,在多处理器环境中,多个线程可以同时运行,但是让我们尝试一下并保持简单;))

线程也可能yield执行,允许系统中的其他线程有机会执行。

你可以试试

 NewThread(String threadname) { name = threadname; t = new Thread(this, name); System.out.println("New thread: " + t); t.start(); // Start the thread // Yield here Thread.yield(); } 

这可能会影响线程运行的方式…同样,你可以sleep一小段时间,但这可能会导致线程被忽略执行一段时间(有时候你想要这个,有时候你不)…

join()方法用于等待被调用的线程不终止,但是在这里的输出中,我们看到线程的交替输出为什么?

你说的问题的方式是错误的… join将等待它被调用的Thread在返回之前死亡。 例如,如果你依赖于一个Thread的结果,你可以使用join来知道什么时候Thread已经结束,然后试图检索它的结果。

同样,你可以轮询线程,但这将吃CPU线程,可以更好地使用Thread而不是… …

JVM和底层操作系统在调度事物时有相当大的自由度。 在看到单个线程的输出之前,你一路“等待线程完成”的事实可能仅仅意味着线程的启动需要更长的时间(也就是说,线程变成“活着“,当run()方法实际开始执行时)。 你可以想象会更早地看到线程输出,但不能保证任何方式。

至于join() ,它只能保证只有当你join的线程完成后才会发生。 所以当你在一行中有三个join()调用时,并不意味着线程应该以特定的顺序结束。 这仅仅意味着你将首先等待ob1 。 一旦ob1完成, ob2ob3可能仍在运行,或者可能已经完成。 如果他们完成,你的其他join()调用将立即返回。

当多个线程访问相同的对象并对其进行更改时,专门使用synchronized 。 保证一个同步块永远不会被两个线程同时执行,即执行它的线程拥有同步的对象。

我的评论:

当我看到输出时,输出与一个,两个,三个线程名称混合在一起,并同时运行。 我不确定你什么时候说线程不是由main方法运行的。

不知道我是否理解你的问题。 但我把我的答案放在我能理解的地方,希望它能帮助你。

1)然后你创build了这个对象,它叫做构造函数,它构造了一个启动方法,启动线程并执行run()方法内部写入的内容。

所以当你创build了3个对象(3个线程 – 一个,两个,三个)时,所有3个线程同时开始执行。

2)join和同步它们是两个不同的东西,同步是当多个线程共享一个公共资源,一个线程应该一次使用这个资源。 例如,像DepositThread,WithdrawThread等线程共享一个共同的对象作为BankObject。 所以,当DepositThread运行时,WithdrawThread将等待它们是否同步。 wait(),notify(),notifyAll()用于线程间通信。 PLZ谷歌了解更多。

关于Join(),当多个线程正在运行,但你join。 例如,如果有两个线程t1和t2并且它们在multithreadingenv中运行,那么输出将是:t1-0 t2-0 t1-1 t2-1 t1-2 t2-2

我们使用t1.join(),它会是:t1-0 t1-1 t1-2 t2-0 t2-1 t2-2

这是在实时使用时,有时你不混淆线程在某些情况下,一个取决于另一个完成(不在共享资源),所以你可以调用join()方法。

使用isAlive()和join()

通常你会希望主线程最后完成。 一个线程如何知道另一个线程何时结束?
final boolean isAlive()
final void join()抛出InterruptedException
join()方法等待一个线程完成。该方法一直等待,直到它所在的线程终止。 它的名字来自调用线程的概念,等待指定的线程join它。 join()的其他forms允许您指定要等待指定的线程终止的最长时间。 这是前面例子的一个改进版本,它使用join()来确保主线程是最后一个停止。 它还演示了isAlive()方法。

  class NewThread implements Runnable { String name; // name of thread Thread t; NewThread(String threadname) { name= threadname; t= new Thread(this ,name); System.out.println("New thread: " + t); t.start(); // Start the thread } // This is the entry point for thread. @Override public void run() { try { for (int i= 5; i > 0; i--) { System.out.println(name + ": " + i); Thread.sleep(1000); } } catch (InterruptedException e) { System.out.println(name + " interrupted."); } System.out.println(name + " exiting."); } } class DemoJoin { public static void main(String args[]) { NewThread ob1= new NewThread("One"); NewThread ob2= new NewThread("Two"); NewThread ob3= new NewThread("Three"); System.out.println("Thread One is alive: " + ob1.t.isAlive()); System.out.println("Thread Two is alive: " + ob2.t.isAlive()); System.out.println("Thread Three is alive: " + ob3.t.isAlive()); // wait for threads to finish try { System.out.println("Waiting for threads to finish."); ob1.t.join(); ob2.t.join(); ob3.t.join(); } catch (Exception e) { System.out.println("Main thread Interrupted"); } System.out.println("Thread One is alive: " + ob1.t.isAlive()); System.out.println("Thread Two is alive: " + ob2.t.isAlive()); System.out.println("Thread Three is alive: " + ob3.t.isAlive()); System.out.println("Main thread exiting."); } } 

当创buildob1时,构造函数被调用,其中“t.start()”被写入,但仍然执行run()方法,而main()方法被进一步执行。 那为什么会这样呢?

在这里你的线程和主线程具有相同的优先级。执行同等优先级的线程完全取决于Thread schedular 。你不能指望首先执行哪个Thread schedular

join()方法用于等待被调用的线程不终止,但是在这里的输出中,我们看到线程的交替输出为什么?

在这里你从主线程调用下面的语句。

  ob1.t.join(); ob2.t.join(); ob3.t.join(); 

因此,主线程等待ob1.tob2.tob3.t线程死掉(查看Thread#join doc ),所有三个线程都成功执行,主线程完成

join()是一个java.lang.Thread类的实例方法,我们可以使用join()方法确保从main开始的所有线程都必须以它们开始的顺序结束,并且main也应该结束。 换句话说,等待这个线程死亡。

exception: join()方法抛出InterruptedException。

线程状态:当线程调用join()方法时,它从运行状态变为等待状态。 等待线程死亡。

同步块:线程在调用join()方法之前不需要获取对象锁,也就是说,可以从外部同步块调用join()方法。

等待时间: join():等待这个线程死掉。

 public final void join() throws InterruptedException; 

这个方法在内部调用join(0)。 而0的超时意味着永远等待;

join(long millis) – 同步方法等待毫秒数毫秒以使这个线程死亡。 0的超时意味着永远等待。

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

连接方法的例子

 class MyThread implements Runnable { public void run() { String threadName = Thread.currentThread().getName(); Printer.print("run() method of "+threadName); for(int i=0;i<4;i++){ Printer.print("i="+i+" ,Thread="+threadName); } } } public class TestJoin { public static void main(String...args) throws InterruptedException { Printer.print("start main()..."); MyThread runnable = new MyThread(); Thread thread1=new Thread(runnable); Thread thread2=new Thread(runnable); thread1.start(); thread1.join(); thread2.start(); thread2.join(); Printer.print("end main()"); } } class Printer { public static void print(String str) { System.out.println(str); } } Output: start main()... run() method of Thread-0 i=0 ,Thread=Thread-0 i=1 ,Thread=Thread-0 i=2 ,Thread=Thread-0 i=3 ,Thread=Thread-0 run() method of Thread-1 i=0 ,Thread=Thread-1 i=1 ,Thread=Thread-1 i=2 ,Thread=Thread-1 i=3 ,Thread=Thread-1 end main() 

注意:调用thread1.join()使主线程等待,直到线程1死亡。

让我们检查一个程序来使用join(long millis)

首先,在Thread-1上会调用join(1000),但是一旦1000 millisec启动,主线程就可以恢复并启动thread2(主线程不会等待Thread-1死掉)。

 class MyThread implements Runnable { public void run() { String threadName = Thread.currentThread().getName(); Printer.print("run() method of "+threadName); for(int i=0;i<4;i++){ try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } Printer.print("i="+i+" ,Thread="+threadName); } } } public class TestJoin { public static void main(String...args) throws InterruptedException { Printer.print("start main()..."); MyThread runnable = new MyThread(); Thread thread1=new Thread(runnable); Thread thread2=new Thread(runnable); thread1.start(); // once 1000 millisec are up, // main thread can resume and start thread2. thread1.join(1000); thread2.start(); thread2.join(); Printer.print("end main()"); } } class Printer { public static void print(String str) { System.out.println(str); } } Output: start main()... run() method of Thread-0 i=0 ,Thread=Thread-0 run() method of Thread-1 i=1 ,Thread=Thread-0 i=2 ,Thread=Thread-0 i=0 ,Thread=Thread-1 i=1 ,Thread=Thread-1 i=3 ,Thread=Thread-0 i=2 ,Thread=Thread-1 i=3 ,Thread=Thread-1 end main() 

有关更多信息,请参阅我的博客

http://javaexplorer03.blogspot.in/2016/05/join-method-in-java.html

没有单词只是运行代码

 // Thread class public class MyThread extends Thread { String result = null; public MyThread(String name) { super(name); } public void run() { for (int i = 0; i < 1000; i++) { System.out.println("Hello from " + this.getName()); } result = "Bye from " + this.getName(); } 

}

主要类

 public class JoinRND { public static void main(String[] args) { System.out.println("Show time"); // Creating threads MyThread m1 = new MyThread("Thread M1"); MyThread m2 = new MyThread("Thread M2"); MyThread m3 = new MyThread("Thread M3"); // Starting out Threads m1.start(); m2.start(); m3.start(); // Just checking current value of thread class variable System.out.println("M1 before: " + m1.result); System.out.println("M2 before: " + m2.result); System.out.println("M3 before: " + m3.result); // After starting all threads main is performing its own logic in // parallel to other threads for (int i = 0; i < 1000; i++) { System.out.println("Hello from Main"); } try { System.out .println("Main is waiting for other threads to get there task completed"); m1.join(); m2.join(); m3.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("M1 after" + m1.result); System.out.println("M2 after" + m2.result); System.out.println("M3 after" + m3.result); System.out.println("Show over"); } 

}

线程调度程序负责调度线程。 所以每次运行程序时,都不能保证线程的执行顺序。 假设你有一个名为threadOne的线程对象,并且如果在threadOne上调用join()如下所示:

threadOne.join()

那么所有当前正在执行的线程将暂停,直到线程1完成其执行或终止。

考虑下面的一段代码:

 class RunnableSample implements Runnable { private Thread t; private String threadName; public RunnableSample(String name) { this.threadName = name; } public void run() { try { for(int i = 4; i >= 1; i--) { System.out.println(Thread.currentThread().getName() + ", " + i); Thread.sleep(500); } } catch (InterruptedException e) { System.out.println(threadName + " interrupted"); } } public void start() { if(t == null) t = new Thread(this, threadName); t.start(); try { t.join(); } catch(Exception e) { System.out.println(e); } } } public class RunnableDemo { public static void main(String[] args) { RunnableSample r1 = new RunnableSample("threadOne"); r1.start(); RunnableSample r2 = new RunnableSample("threadTwo"); r2.start(); RunnableSample r3 = new RunnableSample("threadThree"); r3.start(); } } 

上述程序的输出将是:

 threadOne, 4 threadOne, 3 threadOne, 2 threadOne, 1 threadTwo, 4 threadTwo, 3 threadTwo, 2 threadTwo, 1 threadThree, 4 threadThree, 3 threadThree, 2 threadThree, 1 

由于首先在threadOne上调用join(),threadTwo和threadThree将被暂停,直到threadOne终止。 (注意threadOne,threadTwo和ThreadThree都已经启动了)。 现在线程正在以特定的顺序执行。 如果在我们的例子中没有在一个线程上调用join(),那么将不会有执行线程的顺序。

 public void start() { if(t == null) t = new Thread(this, threadName); t.start(); } 

它的输出将是:

 threadOne, 4 threadThree, 4 threadTwo, 4 threadTwo, 3 threadThree, 3 threadOne, 3 threadOne, 2 threadThree, 2 threadTwo, 2 threadOne, 1 threadThree, 1 threadTwo, 1 

即将到来的同步,如果您想要控制任何共享资源上的多个线程的访问,这是非常有用的。 如果只想限制一个线程访问共享资源,那么同步是最好的方法。