在Java多线程编程中,会涉及到wait、notify、nptifyAll、yield、join、sleep线程间交互的方法,这些比较晦涩难懂,现在全面介绍下这些方法的使用方式。
1. 总览
这些方法可大致分为两类,一类是继承自Object的方法,全部为native实现,一类是Thread的方法,也都是依托native实现的。
1) 继承自Object
- notify()
- notifyAll()
- wait()
- wait(long timeout)
- wait(long timeout, int nanos)
2) Thread的方法
- static yield()
- static sleep(long millis)
- static sleep(long millis, int nanos)
- join(long millis)
- join(long millis, int nanos)
- join()
2. 线程状态转换
2.使用说明
1) wait/wait(time) 与 notify/notifyAll
2) sleep
3) yield
- 代码样例
import java.time.LocalTime;
public class YieldTest {
public static void main(String[] args) {
Thread thread = new Thread(new MyThread());
thread.start();
Thread thread2 = new Thread(new MyThread());
thread2.start();
}
public static class MyThread implements Runnable{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + " " + i + " " + LocalTime.now());
Thread.yield();
System.out.println(Thread.currentThread().getName() + " " + i + " yield " + LocalTime.now());
}
}
}
}
4) join/join(time)
如下代码表示主线程调用了thread的join方法,形成阻塞,thread睡了2秒后,主线程继续执行。
- 代码样例
import java.time.LocalTime;
public class JoinTest {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new MyThread());
thread.start();
System.out.println("Main join wait " + LocalTime.now());
thread.join();
System.out.println("Main end " + LocalTime.now());
}
public static class MyThread implements Runnable{
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
- 输出
Main join wait 00:35:33.265
Main end 00:35:35.199
- 源码解读
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) {
//无限等待至该线程可用死亡(!isAlive())
//isAlive与wait都是native方法
while (isAlive()) {
wait(0); // 复用Object的wait方法
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
参考
- Java线程源码解析之yield和sleep