多个线程并发执行时,在默认情况下CPU是随机切换线程的,有时我们希望CPU按我们的规律执行线程,此时就需要线程之间协调通信
1. 线程通信的方式概述
|--休眠唤醒方式:
|--Object的wait、notify、notifyAll
|--Condition的await、signal、signalAll
|--CountDownLatch:用于某个线程A等待若干个其他线程执行完之后,它才执行
|--CyclicBarrier:一组线程等待至某个状态之后再全部同时执行
|--Semaphore:用于控制对某组资源的访问权限,适合资源少线程多的场景
2. 休眠唤醒方法
2.3. Object的wait、notify、notifyAll
wait/notify
休眠唤醒的方式实现两个线程轮流打印10以内的数
public class WaitNotifyRunnable {
private final Object room = new Object();
private int i = 0;
public void odd(){
while (i<10){
synchronized (room){
while(i%2 != 1){
try {
room.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("奇数"+i);
i++;
room.notifyAll();
}
}
}
public void even(){
while (i<10){
synchronized (room){
while(i%2 != 0){
try {
room.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("偶数"+i);
i++;
room.notifyAll();
}
}
}
public static void main(String[] args) throws InterruptedException {
WaitNotifyRunnable waitNotifyRunnable = new WaitNotifyRunnable();
new Thread(new Runnable() {
@Override
public void run() {
waitNotifyRunnable.odd();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
waitNotifyRunnable.even();
}
}).start();
Thread.sleep(2);
}
}
2.4 Condition的await、signal、signalAll
休眠唤醒的方式实现两个线程轮流打印abc
public class AwaitSignalTest {
public static void main(String[] args) throws InterruptedException {
AwaitAndSignal awaitAndSignal = new AwaitAndSignal(5);
Condition conditionA = awaitAndSignal.newCondition();
Condition conditionB = awaitAndSignal.newCondition();
Condition conditionC = awaitAndSignal.newCondition();
new Thread(()->{
awaitAndSignal.print("a",conditionA ,conditionB);
}).start();
new Thread(()->{
awaitAndSignal.print("b",conditionB ,conditionC);
}).start();
new Thread(()->{
awaitAndSignal.print("c",conditionC ,conditionA);
}).start();
//等他们都在休息室后还需要推他一把 不然都在休息室
TimeUnit.SECONDS.sleep(2);
awaitAndSignal.lock();
try{
conditionA.signalAll();
}finally {
awaitAndSignal.unlock();
}
}
}
class AwaitAndSignal extends ReentrantLock {
private int loopnum;
public AwaitAndSignal(int loopnum) {
this.loopnum = loopnum;
}
public void print(String str, Condition current, Condition next){
for (int i = 0; i < loopnum; i++) {
this.lock();
try {
//先进入休息室
current.await();
System.out.println(str);
next.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
this.unlock();
}
}
}
}