多线程——join()、sleep()

Thread类的方法中有一个join()方法,它是普通的实例方法,根据Java api,该方法有如下三种形式:

void join(): Waits for this thread to die.
void join(long millis): Waits at most millis milliseconds for this thread to die.
void join(long millis, int nanos): Waits at most millis milliseconds plus nanos nanoseconds for this thread to die.

该方法的作用是“等待该线程终止”,一直等待,直到程终止,而带参数的方法的作用是“ 等待该线程终止,至多等待多少毫秒数 (或毫秒数+纳秒数)”。

在此之前,我对这个方法一直有两个疑问,困惑不解:

  1. 为什么这个方法的作用是等待该线程终止,为什么它的名字是“加入”的意思?
  2. 在这个等待的关系中,到底是谁等待谁?

在看了很多人的博客、看了这个方法的源码、看了《Java多线程编程核心技术》这本书和实践之后,我的理解如下,作为自我学习总结。


1. 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;
            }
        }
    }

join(long millis)方法的源代码如上所示,首先该方式是synchronized,其次它的实现原理是调用了wait()方法。

2. join()/wait()与sleep()的区别

由上,所以join()和sleep()这两个方法的区别,本质上是wait()和sleep()这两个方法的区别。

wait()和sleep()的区别:

  • 这两个方法来自不同的类,wait()方法来自Object类,sleep()方法来自Thread类;
  • wait()方法有三种形式:wait()、wait(long timeout)、wait(long timeout, int nanos),而sleep()方法两种形式:sleep(long millis)、sleep(long millis, int nanos),即sleep()方法没有无参形式。其次,sleep()方法是静态方法。
  • 其实区别主要还是来自于这两个方法对同步的处理上:wait()方法会释放锁,sleep()方法不释放锁。在sleep()方法的源代码中有这样一句话:

The thread does not lose ownership of any monitors.

所以join()和sleep()这两个方法的区别,来自于它们对同步的处理上,如上第三条。

3. join()的作用分析

join()方法具有使线程依次串行执行的作用,也就是使线程排队运行。对于t.join()语句,其中的等待关系如下:
join()方法的作用是使线程t正常执行run()方法中的任务,而使当前线程s一直等待线程t终止,
在很多情况下,主线程生成并起动了子线程,所以线程s有可能是主线程,也有可能是其它子线程。
也就是t.join()方法后面的代码,只有等到t线程结束了才能执行。join()方法的使用方式是在线程t启动后直接调用。

代码实例:

功能:三个线程,一个打印A,一个打印B,一个打印C,打印出6个连续的ABC。

/*
 * 三个线程, 一个打印A, 一个打印B, 一个打印C, 打印出6个连续的ABC.
 */
public class PrintABC implements Runnable {
    @Override
    public void run() {
        if(Thread.currentThread().getName().equals("A")){
                System.out.print("A");
        }
        if(Thread.currentThread().getName().equals("B")){
                System.out.print("B");
        }
        if(Thread.currentThread().getName().equals("C")){
                System.out.print("C");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        for(int i=0; i<6; i++){
            PrintABC r = new PrintABC();
            Thread A = new Thread(r, "A");
            A.start();
            A.join();
            Thread B = new Thread(r, "B");
            B.start();
            B.join();
            Thread C = new Thread(r, "C");
            C.start();
            C.join();
        }
    }
}

运行结果:

这里写图片描述

嘻嘻~

这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值