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
在上面的代码中:
-
我不能理解程序的执行stream程,而当
ob1
被创build时,构造函数被调用,其中t.start()
被写入,但仍然run()
方法,而main()
方法继续执行。 那为什么会这样呢? -
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完成, ob2和ob3可能仍在运行,或者可能已经完成。 如果他们完成,你的其他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.t
, ob2.t
, ob3.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
即将到来的同步,如果您想要控制任何共享资源上的多个线程的访问,这是非常有用的。 如果只想限制一个线程访问共享资源,那么同步是最好的方法。