Java并发编程艺术 - Join、Yield和Sleep

Join

join() 的作用:让“主线程”等待“子线程”结束之后才能继续运行。

son.join()被调用的地方是发生在“Father主线程”中,但是son.join()是通过“子线程son”去调用的join(),父线程调用wait()的作用是让“当前线程”等待,而这里的“当前线程”是指当前在CPU上运行的线程。所以,虽然是调用子线程的wait()方法,但是它是通过“主线程”去调用的;所以,休眠的是主线程,而不是“子线程”!

线程join方法

1
2
3
4
public final void join() throws InterruptedException {
//调用父线程
join(0);
}

被调用的父线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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;
}
}
}

Demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args) throws InterruptedException {
AtomicInteger atomicInteger = new AtomicInteger(0);
Runnable runnable = () -> {
do {
log.info(atomicInteger.get() + "- run");
} while (atomicInteger.incrementAndGet() < 10);
log.info(atomicInteger.get() + "- join");
};

Thread thread = new Thread(runnable);
thread.start();
//阻塞,等待子线程执行
thread.join();

log.info(atomicInteger.get() + "- end");
}

执行结果

1
2
3
4
5
6
7
8
9
10
11
12
0- run
1- run
2- run
3- run
4- run
5- run
6- run
7- run
8- run
9- run
10- join
10- end

Yield

1
2
3
4
static void yield( )
导致当前执行线程处于让步状态。如果有其他的可运行线程具有至少与此线程同样高的优先级,那么这些线程接下来会被调度。注意,这是一个静态方法。

`当前线程暂停,给予其他相同优先级或者更高优先级线程执行机会,但不会释放锁`。

Sleep

sleep()方法需要指定等待的时间,它可以让当前正在执行的线程在指定的时间内暂停执行,进入阻塞状态,该方法既可以让其他同优先级或者高优先级的线程得到执行的机会,也可以让低优先级的线程得到执行机会。

但是sleep()方法不会释放“锁标志”,也就是说如果有synchronized同步块,其他线程仍然不能访问共享数据

区别

  • sleep 和yield都不会释放对象的锁,都会导致当前线程等待。

  • sleep具有更大的灵活性,可以指定等待时间,可以唤醒其他更低优先级的线程,会抛出异常;yield只能唤醒同等优先级或者更高优先级的线程,不会给更低优先级线程执行机会,不会抛出异常。

  • yield,sleep都不会释放对象的锁, wait会释放对象的锁。如果不释放对象的锁,其他线程就没办法执行同步的代码。

------ 本文结束------

本文标题:Java并发编程艺术 - Join、Yield和Sleep

文章作者:Perkins

发布时间:2019年09月09日

原始链接:https://perkins4j2.github.io/posts/36650/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。