join()方法原型:
- public final void join() throws InterruptedException
- public final void join(long) throws InterruptedException
- public final void join(long, int) throws InterruptedException
方法说明:举例说明,假设有线程对象A和线程对象B。在线程A中的某个方法中,线程B执行join()操作。当程序运行至B.join()操作的时候,线程A将会挂起,而执行线程B的操作,此时将会产生两种情况:
1、join()方法无参数,则线程A将会等待线程B执行完毕后,再继续执行
2、join()方法带参数(join(m)或者join(m,n)),则代表一个等待时间;当线程B开始执行后,线程A将会等待join()方法中指定的时间之后,不管线程B是否执行完毕,线程A恢复执行。
join()操作的异常及等待时间的处理
方法源代码如下:
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; } } } public final synchronized void join(long millis, int nanos) throws InterruptedException { //当号毫秒数小于0的时候,抛出异常 if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } //当纳秒数小于0或者大于999999时,超范围,抛出异常 if (nanos < 0 || nanos > 999999) { throw new IllegalArgumentException( "nanosecond timeout value out of range"); } //当纳秒数大于500000,或者毫秒数为0而纳秒数不为0的时候,按一毫秒计算 if (nanos >= 500000 || (nanos != 0 && millis == 0)) { millis++; } //调用join(loing)方法 join(millis); } public final void join() throws InterruptedException { join(0); }
示例1:
class Sleeper extends Thread { private int duration; private double d = 0; public Sleeper(String name, int sleepTime) { super(name); duration = sleepTime; start(); } public String toString() { return Thread.currentThread().toString(); } public void run() { try { System.out.println(getName() + " start run()"); sleep(duration); } catch (InterruptedException e) { System.out.println(getName() + " was interrupted. " + "isInterrupted(): " + isInterrupted()); return; } System.out.println(getName() + " has awakened"); //耗时操作 for (int i = 0; i < 900000; i++) { d += (Math.E + Math.PI) / d; } System.out.println(getName() + "执行操作完毕!"); } } class Joiner extends Thread { private Sleeper sleeper; public Joiner(String name, Sleeper sleeper) { super(name); this.sleeper = sleeper; start(); } public String toString() { return Thread.currentThread().toString(); } public void run(){ try { System.out.println(getName() + " start run()"); sleeper.join(); } catch (InterruptedException e) { System.out.println("Interrupted"); } System.out.println(getName() + " join completed"); } } public class Joining { public static void main(String[] args) { Sleeper sleepy = new Sleeper("Sleepy", 5000), grumpy = new Sleeper("Grumpy", 5000); Joiner dopey = new Joiner("Dopey", sleepy), doc = new Joiner("Doc", grumpy); System.out.println("sleepy's id is " + sleepy.getId()); System.out.println("dopey's id is " + dopey.getId()); } }
执行结果 写道
Sleepy start run()
Grumpy start run()
sleepy's id is 8
dopey's id is 10
Dopey start run()
Doc start run()
Sleepy has awakened
Grumpy has awakened
Grumpy执行操作完毕!
Doc join completed
Sleepy执行操作完毕!
Dopey join completed
Grumpy start run()
sleepy's id is 8
dopey's id is 10
Dopey start run()
Doc start run()
Sleepy has awakened
Grumpy has awakened
Grumpy执行操作完毕!
Doc join completed
Sleepy执行操作完毕!
Dopey join completed
分析:
- 根据输出结果分析,前期,所有线程均启动
- dopey中的run()中,sleepy调用join()方法,根据输出的id可以得知,dopey和sleepy并非处于同一线程
- join()方法中无参数,当它被执行的时候,dopey会等待,直到sleepy执行完毕,dopey才会继续执行
示例2:将示例1中join()方法改为join(500)
执行结果 写道
sleepy's id is 8
dopey's id is 10
Sleepy start run()
Grumpy start run()
Dopey start run()
Doc start run()
Dopey join completed
Doc join completed
Sleepy has awakened
Grumpy has awakened
Sleepy执行操作完毕!
Grumpy执行操作完毕!
dopey's id is 10
Sleepy start run()
Grumpy start run()
Dopey start run()
Doc start run()
Dopey join completed
Doc join completed
Sleepy has awakened
Grumpy has awakened
Sleepy执行操作完毕!
Grumpy执行操作完毕!
分析:当join()加入参数500后,dopey只会等待sleepy500毫秒,在这个时间只会dopey会继续执行,而不会管sleepy是否会执行完毕。
join()的异常,示例:
class DemoA extends Thread { private double d = 0.0; public DemoA() { start(); } public void run() { System.out.println("start DemoA!"); while (!this.isInterrupted()) { for (int i = 0; i < 900000; i++) { d = d + (Math.PI + Math.E) / d; } //System.out.println("d = " + d); } System.out.println("end DemoA!"); } } class DemoB extends Thread { private Thread demo; public DemoB(Thread demo) { this.demo = demo; start(); } public void run() { System.out.println("start DemoB!"); try { demo.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("end DemoB!"); } } public class Hello { public static void main(String[] args) throws InterruptedException { DemoA a = new DemoA(); DemoB b = new DemoB(a); Thread.sleep(2000); b.interrupt(); Thread.sleep(2000); System.out.println("DemoA intreeupted is " + a.isInterrupted()); System.out.println("DemoB intreeupted is " + b.isInterrupted()); } }
执行结果 写道
start DemoA!
start DemoB!
end DemoB!
DemoA intreeupted is false
DemoB intreeupted is false
java.lang.InterruptedException
at java.lang.Object.wait(Native Method)
at java.lang.Thread.join(Thread.java:1280)
at java.lang.Thread.join(Thread.java:1354)
at com.test4.DemoB.run(Hello.java:35)
start DemoB!
end DemoB!
DemoA intreeupted is false
DemoB intreeupted is false
java.lang.InterruptedException
at java.lang.Object.wait(Native Method)
at java.lang.Thread.join(Thread.java:1280)
at java.lang.Thread.join(Thread.java:1354)
at com.test4.DemoB.run(Hello.java:35)
分析:当DemoB执行中断操作的时候,join()方法会产生异常,并且再得到DemoB的中断状态为false;根据JavaAPI得知,调用join()方法,如果一个线程中断了当前线程,会抛出java.lang.InterruptedException异常,并且线程的中断状态被清除。
注:本文代码原型源自《Think in Java》(Fourth Edition)中"21.2.11加入一个线程"。
本文是目前个人理解的结果,仅供参考,如后续发现问题,本人会进行相应的更正,也欢迎各位对Java线程感兴趣的朋友或者前辈进行指正。
相关推荐
Java线程:概念与原理 2 一、操作系统中线程和进程的概念 2 二、Java中的线程 3 三、Java中关于线程的名词解释 3 四、线程的状态转换和生命周期 4 Java线程:创建与启动 7 Java线程:线程名称的设定及获取 10 Java...
java线程学习笔记
Java线程:线程的同步-同步方法 Java线程:线程的同步-同步块 Java线程:并发协作-生产者消费者模型 Java线程:并发协作-死锁 Java线程:volatile关键字 Java线程:新特征-线程池 Java线程:新特征-有返回值的线程 ...
Java线程:线程的同步-同步方法 Java线程:线程的同步-同步块 Java线程:并发协作-生产者消费者模型 Java线程:并发协作-死锁 Java线程:volatile关键字 Java线程:新特征-线程池 Java线程:新特征-有返回值的...
java学习笔记2(多线程)java学习笔记2(多线程)
多线程学习笔记,通过平时的学习所做的一些笔记,希望对广大同仁有所帮助
Java线程:线程的同步-同步方法 Java线程:线程的同步-同步块 Java线程:并发协作-生产者消费者模型 Java线程:并发协作-死锁 Java线程:volatile关键字 Java线程:新特征-线程池 Java线程:新特征-有返回值的线程 ...
NULL 博文链接:https://baobeituping.iteye.com/blog/1190260
java 线程Dump 分析工具: Java的TDA线程转储分析器是一个用于分析Sun Java VM生成的线程转储和堆信息的小型Swing GUI(目前用1.4测试)。它从提供的日志文件中解析线程转储和类直方图。它提供关于发现的线程转储的...
花费了一上午的时候 写了一些demo。认识到四种线程池的区别。上传到csdn 供以后学习
Java线程:概念与原理 Java线程:创建与启动 Java线程:线程状态的转换 Java线程:线程的同步与锁 一、同步问题提出 二、同步和锁定 三、静态方法同步 四、如果线程不能不能获得锁会怎么样 五、何时需要同步...
电子书相关:包含4个有关JAVA线程的电子书(几乎涵盖全部有关线程的书籍) ...第六章 Java线程调度 第七章 Java线程调度例子 第八章 和同步相关的高级主题 第九章 多处理器机器上的并行化 第十章 线程组
java线程 线程 教程 java线程教程 java线程学习资料 本教程有什么内容? 本教程研究了线程的基础知识— 线程是什么、线程为什么有用以及怎么开始编写使用线程的简单 程序。 我们还将研究更复杂的、使用线程的应用...
多线程学习笔记,好资源。包括线程基础等知识多线程学习笔记,好资源。包括线程基础等知识
Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java...