这篇文章主要讲解Java多线程之间的几种通信方式:wait() + notify() (Object)
await() + signal() (condition 条件锁)
join方式
前三种通信方式主要通过一种线程同步的场景进行讲解:假设有a()、b()、c()两个任务分别有三个线程执行,要求a,b,c顺序执行。
public class TaskA implements Runnable {
@Override
public void run() {
a();
}
private void a() {
System.out.println("a 开始执行");
System.out.println("========a任务========");
System.out.println("a 执行完毕");
}
}
TaskB和TaskC类似。运行测试代码:
public class Process {
public void process(){
Thread threadA = new Thread(new TaskA());
Thread threadB = new Thread(new TaskB());
Thread threadC = new Thread(new TaskC());
threadA.start();
threadB.start();
threadC.start();
}
public static void main(String[] args) {
Process process = new Process();
process.process();
}
}
结果如下fig1.无序的结果
可见,顺序无法保证。wait() + notify()
public class Process {
public static Integer signal = 1;
public Object lock = new Object(); // 加入锁
public void process() {
Thread threadA = new Thread(new TaskA(lock));
Thread threadB = new Thread(new TaskB(lock));
Thread threadC = new Thread(new TaskC(lock));
threadA.start();
threadB.start();
threadC.start();
}
public static void main(String[] args) {
Process process = new Process();
process.process();
}
}
public class TaskA implements Runnable {
private Object lock;
public TaskA(Object lock){
this.lock = lock;
}
@Override
public void run() {
while(true) {
synchronized (lock) {
while (Process.signal != 1) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
a();
Process.signal = 2
lock.notifyAll();
}
}
}
}
使用wait(),notify(),可以保证线程不运行时释放CPU资源。
await() + signal() (condition 条件锁)
条件锁可以指定要唤醒的线程,而不是每一个都唤醒。
public class Process {
public static Integer signal = 1;
ReentrantLock lock = new ReentrantLock();
public void process() {
Condition a = lock.newCondition();
Condition b = lock.newCondition();
Condition c = lock.newCondition();
Thread threadA = new Thread(new TaskA(lock,a,b));
Thread threadB = new Thread(new TaskB(lock,b,c));
Thread threadC = new Thread(new TaskC(lock,a,c));
threadA.start();
threadB.start();
threadC.start();
}
}
public class TaskA implements Runnable {
private ReentrantLock lock;
private Condition a;
private Condition b;
public TaskA(ReentrantLock lock, Condition a, Condition b) {
this.lock = lock;
this.a = a;
this.b = b;
}
@Override
public void run() {
while (true) {
lock.lock();
// 如果不等于1,自旋
while (Process.signal != 1) {
try {
a.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
a();
Process.signal = 2;
b.signal();
lock.unlock();
}
}
}join方式
join方式可以保证一个线程在一个线程之后执行,通过传入具体的线程可以解决。
public class TaskA implements Runnable {
@Override
public void run() {
a();
}
private void a() {
System.out.println("a 开始执行");
System.out.println("=======a任务=======");
System.out.println("a 执行完毕");
}
}
public class TaskB implements Runnable {
private Thread joinThread;
public TaskB(Thread joinThread) {
this.joinThread = joinThread;
}
@Override
public void run() {
b(joinThread);
}
private void b(Thread joinThread) {
try {
joinThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("b 开始执行");
System.out.println("=======b任务=======");
System.out.println("b 执行完毕");
}
}
public class Process {
public void process() {
Thread threadA = new Thread(new TaskA());
Thread threadB = new Thread(new TaskB(threadA));
threadA.start();
threadB.start();
}
public static void main(String[] args) {
Process process = new Process();
process.process();
}
}