`

Java线程学习笔记(六):join()方法

    博客分类:
  • Java
阅读更多

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

 分析:

  • 根据输出结果分析,前期,所有线程均启动
  • 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执行操作完毕!

 分析:当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)

 分析:当DemoB执行中断操作的时候,join()方法会产生异常,并且再得到DemoB的中断状态为false;根据JavaAPI得知,调用join()方法,如果一个线程中断了当前线程,会抛出java.lang.InterruptedException异常,并且线程的中断状态被清除。

 

注:本文代码原型源自《Think in Java》(Fourth Edition)中"21.2.11加入一个线程"。

本文是目前个人理解的结果,仅供参考,如后续发现问题,本人会进行相应的更正,也欢迎各位对Java线程感兴趣的朋友或者前辈进行指正。

分享到:
评论

相关推荐

    java线程学习笔记

    Java线程学习笔记涉及了Java多线程编程的多个关键知识点,本篇知识点整理将详细解释每个概念及其在Java中的实现方式。 基本知识部分包含了Java线程编程的基础内容,它们是并发编程的基石。 任务Runnable是一个接口...

    Java多线程学习笔记

    ### Java多线程学习笔记 #### 一、线程的基本概念 在计算机科学中,**线程**(Thread)是程序执行流的最小单位。一个标准的程序只能做一件事情,而通过多线程技术,可以让程序同时处理多个任务。在Java中,线程是...

    java多线程笔记

    Java线程是多任务编程的重要组成部分,它允许程序同时执行多个独立的代码片段,从而提高程序的效率和响应性。本文将深入探讨Java线程的概念、原理以及如何在实际编程中进行有效管理。 首先,我们要了解操作系统中的...

    Java多线程详解(超详细)_狂神说笔记完整版_项目代码_适合小白随课程学习

    - `join()`方法使主线程等待子线程结束。 - `yield()`方法让当前线程暂停,让其他线程有机会执行。 4. **线程同步** - 当多个线程访问共享资源时,需要进行同步控制,防止数据不一致。 - `synchronized`关键字...

    java多线程学习笔记

    Java提供了Thread类的一些方法来控制线程,如sleep()使线程暂停指定时间,yield()让当前线程暂停并让其他相同优先级的线程有机会运行,join()使当前线程等待指定线程结束后再继续。 同步机制是Java多线程中防止数据...

    Java JDK 7学习笔记 PDF

    3. **多线程改进**:JDK 7提供了`Fork/Join`框架,这是一种基于工作窃取算法的并行编程模型,用于高效地执行大量可分解的任务。 4. **try-with-resources语句**:这个新特性允许自动关闭实现了`AutoCloseable`接口...

    java_Java_学习笔记.zip

    这份"java_Java_学习笔记.zip"包含了丰富的Java基础知识,对于初学者来说是极好的参考资料。以下是一些主要的知识点概述: 1. **Java简介**: - Java由Sun Microsystems开发,后被Oracle公司收购。 - Java的设计...

    多线程学习笔记,关于创建线程,删除线程等相关指令的应用。

    - **pthread_exit**:线程结束并返回退出状态码,joinable线程需要被`pthread_join`回收资源。 - **pthread_join**:等待指定线程结束并回收其资源。 了解并掌握这些多线程的基本操作对于编写高效并发应用程序至...

    Java实验9多线程设计.doc

    - **题3**:模拟三个线程(代表老师)分发学习笔记,可以使用synchronized关键字或Lock接口(如ReentrantLock)确保线程安全地分配资源。 8. **实验结果和分析**: 实验的结果将展示线程并发执行的特点,例如线程...

    java多线程代码笔记

    此外,`Thread.join()`方法允许一个线程等待另一个线程完成其执行,而`Thread.sleep(long millis)`则让当前线程暂停指定的毫秒数。 在`day24_Thread`和`day23_Thread`的文件中,可能涵盖了线程的优先级、守护线程、...

    CoreJava学习笔记

    ### CoreJava学习笔记 #### 一、JAVA特点与运行原理 **JAVA特点:** 1. **简单性**:Java的设计者们将C++语言中许多不易理解和容易混淆的部分去除,使得Java更容易理解与掌握。 2. **面向对象**:Java几乎一切都...

    java笔记 java笔记

    - **线程方法**:如`start()`、`run()`、`join()`等。 - **并发处理**:多个线程访问共享资源时需要注意同步问题。 - **互斥锁**:使用`synchronized`关键字或其他同步机制来控制线程对共享资源的访问。 #### 15. ...

    Java多线程文章系列.pdf

    #### 五、Java多线程学习笔记 ##### 1. 线程类 - **Thread类**: - 提供了创建和控制线程的方法。 - 可以通过继承`Thread`类或实现`Runnable`接口来创建线程。 ##### 2. 等待一个线程的结束 - **join()方法**: -...

    Java JDK 8学习笔记 带完整书签(不是页码书签哦)

    《Java JDK 8学习笔记》是由林信良教授在2015年3月出版的一本详尽解析Java SE 8新特性的书籍,由清华大学出版社发行。这本书共计643页,内容完整且清晰,包含目录和书签,便于读者高效地查阅和学习。 在Java JDK 8...

    Java入门学习笔记

    ### Java入门学习笔记 #### 一、Java特点与运行原理 **1.1 Java特点** - **简单性:** Java的设计使得它易于学习且避免了许多传统编程语言中存在的复杂性。 - **面向对象:** Java是一种纯面向对象的语言,支持...

    Java并发编程学习笔记.

    2. **并发基础**:Java并发编程的基础包括`Thread.start()`启动线程,`Thread.join()`等待线程结束,以及`Thread.sleep()`让当前线程暂停一段时间。 3. **同步机制**:Java提供了多种同步机制,如`synchronized`...

    Java学习笔记——良葛格

    【Java学习笔记——良葛格】是一份由爱好者良葛格整理的Java学习资料,主要以PDF格式呈现,虽然可能不完整,但包含了丰富的Java编程基础知识和实践技巧,旨在为初学者提供一个学习和参考的平台。以下是笔记中可能...

    java学习笔记

    Java学习笔记的知识点如下: 一、Java基础 1. 编程语言和Java特点:Java是一种高级、面向对象、多线程的编程语言,具有跨平台性、面向对象、安全性、多线程等特点。 2. Java开发环境配置:Java开发需要配置JDK...

    java学习笔记.zip

    在这个"java学习笔记.zip"压缩包中,我们可能找到了一系列关于Java 7的学习资料,涵盖了基础知识到高级特性的讲解。 1. **基础概念**:Java的基础包括语法结构、数据类型、变量、运算符、控制流(如if语句、switch...

    java基础笔记,多线程、反射、java8

    Java提供了丰富的线程控制方法,如start()启动线程,sleep()使线程休眠,join()等待线程结束,synchronized关键字用于线程同步,防止数据竞争。此外,ExecutorService和Future接口提供了一种更灵活的线程管理机制,...

Global site tag (gtag.js) - Google Analytics