Thread.Join()简单分析

Thread.Join()

1. 知识了解背景:

Java支持多线程,CPU分配给线程的时间片是随机的,有时需要控制线程的执行顺序,如执行完thread1再去执行thread2。引入join

JDK 8 中 join() 一共有三个重载方法,无参、一个参数、两个参数:

在这里插入图片描述

JDK源码
public final void join() throws InterruptedException {
    join(0);
}

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 {

    if (millis < 0) {
        throw new IllegalArgumentException("timeout value is negative");
    }

    if (nanos < 0 || nanos > 999999) {
        throw new IllegalArgumentException(
                            "nanosecond timeout value out of range");
    }

    if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
        millis++;
    }

    join(millis);
}

(1) 三个方法都被final修饰,无法被子类重写。
(2) join(long), join(long, long) 是synchronized method,同步的对象是当前线程实例。
(2) 无参版本和两个参数版本最终都调用了一个参数的版本。
(3) join() 和 join(0) 是等价的,表示一直等下去;join(非0)表示等待一段时间。
从源码可以看到 join(0) 调用了Object.wait(0),其中Object.wait(0) 会一直等待,直到被notify/中断才返回。
while(isAlive())是为了防止子线程伪唤醒(spurious wakeup),只要子线程没有TERMINATED的,父线程就需要继续等下去。
(4) join() 和 sleep() 一样,可以被中断(被中断时,会抛出 InterrupptedException 异常);不同的是,join() 内部调用了 wait(),会出让锁,而 sleep() 会一直保持锁。

2.实例:模拟同步做菜线程串行执行系统解释Thread.Join()

//父线程
public class test {
	public static void main(String[] args) throws InterruptedException {
		//记录开始时间
		System.out.println("模拟同步操作做菜");
		long start=System.currentTimeMillis();
		//等待凉菜,必须要返回结果,所以要调用join方法
		Thread t1=new ColdDishThread();
		t1.start();
		t1.join();
		
		//同理等待包子,必须要返回结果,所以要调用join方法
		Thread t2=new BumThread();
		t2.start();
		//t1.join();
		t2.join();
		long end =System.currentTimeMillis();
		System.out.println("总共:"+((end-start)/1000)+"分钟做好");
	}

}

//子线程1:
public class BumThread extends Thread {
	public void run(){
		try {
			Thread.sleep(3000);
			System.out.println("包子3分钟蒸好了");
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

//子线程2:

public class ColdDishThread extends Thread {
public void run(){
	try {
		Thread.sleep(1000);阻塞线程,休眠一秒钟
		/*
		1.Thread.sleep(毫秒)
		2.sleep方法是一个静态方法
		3.该方法的作用:阻塞该线程,让给其他线程
	    */
		System.out.println("凉菜花费1分钟做好");
	} catch (InterruptedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
}
}

2.1~~**分析:**父线程test,俩子线程ColdDishThread()和BumThread()线程的执行顺序~~

1. 先从父线程的main()方法进入,执行子线程t1先new->t1.star()->t1.join()
子线程t1执行完之后,返回父线程main()执行t2new->t2.star()->t3.join()
2. 如果t1线程没有运行结束, 那么main就会一直阻塞在”t.join()“这里。

2.2Thread.Join()作用

** 当我们调用某个线程的join()时,join会挂起调用线程,直到被调用线程结束执行,调用线程才会继续执行。**

参考:
https://www.cnblogs.com/huangzejun/p/7908898.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值