`

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线程:概念与原理 2 一、操作系统中线程和进程的概念 2 二、Java中的线程 3 三、Java中关于线程的名词解释 3 四、线程的状态转换和生命周期 4 Java线程:创建与启动 7 Java线程:线程名称的设定及获取 10 Java...

    java线程学习笔记

    java线程学习笔记

    java多线程编程总结

    Java线程:线程的同步-同步方法 Java线程:线程的同步-同步块 Java线程:并发协作-生产者消费者模型 Java线程:并发协作-死锁 Java线程:volatile关键字 Java线程:新特征-线程池 Java线程:新特征-有返回值的线程 ...

    Java多线程编程总结

    Java线程:线程的同步-同步方法 Java线程:线程的同步-同步块 Java线程:并发协作-生产者消费者模型 Java线程:并发协作-死锁 Java线程:volatile关键字 Java线程:新特征-线程池 Java线程:新特征-有返回值的...

    java学习笔记2(多线程)

    java学习笔记2(多线程)java学习笔记2(多线程)

    多线程学习笔记

    多线程学习笔记,通过平时的学习所做的一些笔记,希望对广大同仁有所帮助

    Java 线程总结

    Java线程:线程的同步-同步方法 Java线程:线程的同步-同步块 Java线程:并发协作-生产者消费者模型 Java线程:并发协作-死锁 Java线程:volatile关键字 Java线程:新特征-线程池 Java线程:新特征-有返回值的线程 ...

    JAVA 多线程学习笔记

    NULL 博文链接:https://baobeituping.iteye.com/blog/1190260

    java 线程 dump 分析工具 2.3.3

    java 线程Dump 分析工具: Java的TDA线程转储分析器是一个用于分析Sun Java VM生成的线程转储和堆信息的小型Swing GUI(目前用1.4测试)。它从提供的日志文件中解析线程转储和类直方图。它提供关于发现的线程转储的...

    java 线程总结笔记

    花费了一上午的时候 写了一些demo。认识到四种线程池的区别。上传到csdn 供以后学习

    java线程详解

    Java线程:概念与原理 Java线程:创建与启动 Java线程:线程状态的转换 Java线程:线程的同步与锁 一、同步问题提出 二、同步和锁定 三、静态方法同步 四、如果线程不能不能获得锁会怎么样 五、何时需要同步...

    线程 JAVA java线程 java线程第3版 java线程第2版第3版合集

    电子书相关:包含4个有关JAVA线程的电子书(几乎涵盖全部有关线程的书籍) ...第六章 Java线程调度 第七章 Java线程调度例子 第八章 和同步相关的高级主题 第九章 多处理器机器上的并行化 第十章 线程组

    java线程 线程学习资料 java线程教程

    java线程 线程 教程 java线程教程 java线程学习资料 本教程有什么内容? 本教程研究了线程的基础知识— 线程是什么、线程为什么有用以及怎么开始编写使用线程的简单 程序。 我们还将研究更复杂的、使用线程的应用...

    Java多线程笔记

    多线程学习笔记,好资源。包括线程基础等知识多线程学习笔记,好资源。包括线程基础等知识

    Java多线程学习Java多线程学习Java多线程学习Java多线程学习.txt

    Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java...

Global site tag (gtag.js) - Google Analytics