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线程学习笔记涉及了Java多线程编程的多个关键知识点,本篇知识点整理将详细解释每个概念及其在Java中的实现方式。 基本知识部分包含了Java线程编程的基础内容,它们是并发编程的基石。 任务Runnable是一个接口...
### Java多线程学习笔记 #### 一、线程的基本概念 在计算机科学中,**线程**(Thread)是程序执行流的最小单位。一个标准的程序只能做一件事情,而通过多线程技术,可以让程序同时处理多个任务。在Java中,线程是...
Java线程是多任务编程的重要组成部分,它允许程序同时执行多个独立的代码片段,从而提高程序的效率和响应性。本文将深入探讨Java线程的概念、原理以及如何在实际编程中进行有效管理。 首先,我们要了解操作系统中的...
- `join()`方法使主线程等待子线程结束。 - `yield()`方法让当前线程暂停,让其他线程有机会执行。 4. **线程同步** - 当多个线程访问共享资源时,需要进行同步控制,防止数据不一致。 - `synchronized`关键字...
Java提供了Thread类的一些方法来控制线程,如sleep()使线程暂停指定时间,yield()让当前线程暂停并让其他相同优先级的线程有机会运行,join()使当前线程等待指定线程结束后再继续。 同步机制是Java多线程中防止数据...
3. **多线程改进**:JDK 7提供了`Fork/Join`框架,这是一种基于工作窃取算法的并行编程模型,用于高效地执行大量可分解的任务。 4. **try-with-resources语句**:这个新特性允许自动关闭实现了`AutoCloseable`接口...
这份"java_Java_学习笔记.zip"包含了丰富的Java基础知识,对于初学者来说是极好的参考资料。以下是一些主要的知识点概述: 1. **Java简介**: - Java由Sun Microsystems开发,后被Oracle公司收购。 - Java的设计...
- **pthread_exit**:线程结束并返回退出状态码,joinable线程需要被`pthread_join`回收资源。 - **pthread_join**:等待指定线程结束并回收其资源。 了解并掌握这些多线程的基本操作对于编写高效并发应用程序至...
- **题3**:模拟三个线程(代表老师)分发学习笔记,可以使用synchronized关键字或Lock接口(如ReentrantLock)确保线程安全地分配资源。 8. **实验结果和分析**: 实验的结果将展示线程并发执行的特点,例如线程...
此外,`Thread.join()`方法允许一个线程等待另一个线程完成其执行,而`Thread.sleep(long millis)`则让当前线程暂停指定的毫秒数。 在`day24_Thread`和`day23_Thread`的文件中,可能涵盖了线程的优先级、守护线程、...
### CoreJava学习笔记 #### 一、JAVA特点与运行原理 **JAVA特点:** 1. **简单性**:Java的设计者们将C++语言中许多不易理解和容易混淆的部分去除,使得Java更容易理解与掌握。 2. **面向对象**:Java几乎一切都...
- **线程方法**:如`start()`、`run()`、`join()`等。 - **并发处理**:多个线程访问共享资源时需要注意同步问题。 - **互斥锁**:使用`synchronized`关键字或其他同步机制来控制线程对共享资源的访问。 #### 15. ...
#### 五、Java多线程学习笔记 ##### 1. 线程类 - **Thread类**: - 提供了创建和控制线程的方法。 - 可以通过继承`Thread`类或实现`Runnable`接口来创建线程。 ##### 2. 等待一个线程的结束 - **join()方法**: -...
《Java JDK 8学习笔记》是由林信良教授在2015年3月出版的一本详尽解析Java SE 8新特性的书籍,由清华大学出版社发行。这本书共计643页,内容完整且清晰,包含目录和书签,便于读者高效地查阅和学习。 在Java JDK 8...
### Java入门学习笔记 #### 一、Java特点与运行原理 **1.1 Java特点** - **简单性:** Java的设计使得它易于学习且避免了许多传统编程语言中存在的复杂性。 - **面向对象:** Java是一种纯面向对象的语言,支持...
2. **并发基础**:Java并发编程的基础包括`Thread.start()`启动线程,`Thread.join()`等待线程结束,以及`Thread.sleep()`让当前线程暂停一段时间。 3. **同步机制**:Java提供了多种同步机制,如`synchronized`...
【Java学习笔记——良葛格】是一份由爱好者良葛格整理的Java学习资料,主要以PDF格式呈现,虽然可能不完整,但包含了丰富的Java编程基础知识和实践技巧,旨在为初学者提供一个学习和参考的平台。以下是笔记中可能...
Java学习笔记的知识点如下: 一、Java基础 1. 编程语言和Java特点:Java是一种高级、面向对象、多线程的编程语言,具有跨平台性、面向对象、安全性、多线程等特点。 2. Java开发环境配置:Java开发需要配置JDK...
在这个"java学习笔记.zip"压缩包中,我们可能找到了一系列关于Java 7的学习资料,涵盖了基础知识到高级特性的讲解。 1. **基础概念**:Java的基础包括语法结构、数据类型、变量、运算符、控制流(如if语句、switch...
Java提供了丰富的线程控制方法,如start()启动线程,sleep()使线程休眠,join()等待线程结束,synchronized关键字用于线程同步,防止数据竞争。此外,ExecutorService和Future接口提供了一种更灵活的线程管理机制,...