多线程编程-线程间通信-join方法的使用(六)

傷城~ 2022-06-01 02:13 273阅读 0赞

方法join的使用

1,主线程启动子线程后,如果主线程项等子线程执行完成后再结束,就要用到join()方法了。

测试代码:

  1. public class JoinThread extends Thread{
  2. @Override
  3. public void run() {
  4. try {
  5. int value = (int)(Math.random()*10000);
  6. System.out.println(value);
  7. Thread.sleep(value);
  8. } catch (InterruptedException e) {
  9. e.printStackTrace();
  10. }
  11. }
  12. }
  13. public class RunTest {
  14. public static void main(String[] args) {
  15. try {
  16. JoinThread jt = new JoinThread();
  17. jt.start();
  18. jt.join();
  19. System.out.println("after joinThread finish,print this");
  20. } catch (InterruptedException e) {
  21. e.printStackTrace();
  22. }
  23. }
  24. }

运行结果:

3231
after joinThread finish,print this

方法join的作用是使所属的线程对象t正常执行run()方法中的任务,而使当前线程m进入无限期阻塞,等待t线程运行结束销毁后在继续执行m线程后面的代码。

Join方法具有使线程排队运行的作用,类似同步的运行结果。与synchronized方法的区别:join方法实际是一个synchronized方法,内部使用wait()方法进行等待,而synchronized关键字使用的是“对象监视器”机制做同步。

2,在join的过程中,如果当前线程对象被中断,则当前线程出现异常。

测试代码:

  1. public class ThreadA extends Thread{
  2. @Override
  3. public void run() {
  4. for(int i=0; i<Integer.MAX_VALUE; i++){
  5. String str = new String();
  6. Math.random();
  7. }
  8. }
  9. }
  10. public class ThreadB extends Thread{
  11. @Override
  12. public void run() {
  13. try {
  14. ThreadA ta = new ThreadA();
  15. ta.start();
  16. ta.join();
  17. System.out.println("thread B run end.");
  18. } catch (InterruptedException e) {
  19. System.out.println("thread B InterruptedException.");
  20. e.printStackTrace();
  21. }
  22. }
  23. }
  24. public class ThreadC extends Thread{
  25. private ThreadB tb;
  26. public ThreadC(ThreadB tb){
  27. super();
  28. this.tb = tb;
  29. }
  30. @Override
  31. public void run() {
  32. tb.interrupt();
  33. }
  34. }
  35. public class RunTest {
  36. public static void main(String[] args) {
  37. try {
  38. ThreadB tb = new ThreadB();
  39. tb.start();
  40. Thread.sleep(500);
  41. ThreadC tc = new ThreadC(tb);
  42. tc.start();
  43. } catch (InterruptedException e) {
  44. e.printStackTrace();
  45. }
  46. }
  47. }

运行结果:

thread B InterruptedException.
java.lang.InterruptedException
at java.lang.Object.wait(Native Method)
at java.lang.Thread.join(Unknown Source)
at java.lang.Thread.join(Unknown Source)
at ThreadB.run(ThreadB.java:9)

Join方法和interrupt方法彼此遇到,就会出异常。

3,join(long),可以设定等待的时间。

跟Thread.sleep(long)方法的区别,Thread.sleep(long)方法不会释放锁。

测试代码,验证:Thread.sleep(long)方法不会释放锁。

  1. public class ThreadA extends Thread{
  2. private ThreadB tb;
  3. public ThreadA(ThreadB tb){
  4. super();
  5. this.tb = tb;
  6. }
  7. @Override
  8. public void run() {
  9. try {
  10. synchronized(tb){
  11. tb.start();
  12. System.out.println("ta run begin time ="+System.currentTimeMillis());
  13. Thread.sleep(6000);
  14. System.out.println("ta run end time ="+System.currentTimeMillis());
  15. }
  16. } catch (InterruptedException e) {
  17. e.printStackTrace();
  18. }
  19. }
  20. }
  21. public class ThreadB extends Thread{
  22. @Override
  23. public void run() {
  24. try {
  25. System.out.println("tb run begin time ="+System.currentTimeMillis());
  26. Thread.sleep(5000);
  27. System.out.println("tb run end time ="+System.currentTimeMillis());
  28. } catch (InterruptedException e) {
  29. System.out.println("thread B InterruptedException.");
  30. e.printStackTrace();
  31. }
  32. }
  33. synchronized public void tbService(){
  34. System.out.println("print tb service timer="+System.currentTimeMillis());
  35. }
  36. }
  37. public class ThreadC extends Thread{
  38. private ThreadB tb;
  39. public ThreadC(ThreadB tb){
  40. super();
  41. this.tb = tb;
  42. }
  43. @Override
  44. public void run() {
  45. tb.tbService();
  46. }
  47. }
  48. public class RunTest {
  49. public static void main(String[] args) {
  50. try {
  51. ThreadB tb = new ThreadB();
  52. ThreadA ta = new ThreadA(tb);
  53. ta.start();
  54. Thread.sleep(2000);
  55. ThreadC tc = new ThreadC(tb);
  56. tc.start();
  57. } catch (InterruptedException e) {
  58. e.printStackTrace();
  59. }
  60. }
  61. }

运行结果:

ta run begin time =1516180072939
tb run begin time =1516180072939
tb run end time =1516180077940
ta run end time =1516180078940
print tb service timer=1516180078940

可以看到,print tb service timer=1516180078940 这句没有马上输出,而是等到ta的sleep时间到了之后才输出。

因为ta的sleep方法一直持有tb对象的锁,时间是6秒,所以tc只有在6s后,ta释放了tb锁后,才能调用tb的同步方法synchronized public void tbService(){}

修改ThreadA的run方法,把sleep(6000)改成tb.join(),运行结果:

tb run begin time =1516180439457
ta run begin time =1516180439457
print tb service timer=1516180441472
tb run end time =1516180444457
ta run end time =1516180444457

由于join方法释放了锁,tbService方法可以马上执行。

发表评论

表情:
评论列表 (有 0 条评论,273人围观)

还没有评论,来说两句吧...

相关阅读

    相关 线通信Thread.join

    在很多应用场景中存在这样一种情况,主线程创建并启动子线程后,如果子线程要进行很耗时的计算,那么主线程将比子线程先结束,但是主线程需要子线程的计算的结果来进行自己下一步的计算,这