@TOC
转自 极客时间
线程协作工具类就是帮助程序员更容易的让线程之间进行协作,来完成某个业务功能。
CountDownLatch倒数门闩
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* CountDownLatch案例:6个程序猿加班
* 当计数器的值变为0时,因await方法阻塞的线程会被唤醒,继续执行
*/
public class Demo11CountDownLatch {
public static void main(String[] args) throws InterruptedException {
//计数门闩
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 1; i <= 6; i++) {
new Thread(()->{
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {e.printStackTrace(); }
System.out.println(Thread.currentThread().getName() + "\t上完班,离开公司");
countDownLatch.countDown();
}, String.valueOf(i)).start();
}
new Thread(()->{
try {
countDownLatch.await();
System.out.println(Thread.currentThread().getName()+"\t卷王最后关灯走人");
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "7").start();
}
}
Semaphore信号量
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
/**
* Semaphore案例:三辆小汽车抢车位
* Semaphore信号量主要作用:1.用于多个共享资源的互斥使用,2.用于并发线程数的控制
*/
public class Demo12Semaphore {
public static void main(String[] args) {
//模拟资源类,有3个空车位
Semaphore semaphore = new Semaphore(3);
for (int i = 1; i <= 6; i++) {
new Thread(()->{
try{
//占有资源
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"\t抢到车位");
try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) {e.printStackTrace(); }
System.out.println(Thread.currentThread().getName()+"\t停车3秒后离开车位");
} catch (Exception e) {
e.printStackTrace();
} finally {
//释放资源
semaphore.release();
}
}, "Thread-Car-"+String.valueOf(i)).start();
}
}
}
CyclicBarrier循环栅栏
import java.util.concurrent.CyclicBarrier;
/**
* 案例:集齐7龙珠召唤神龙
*/
public class Demo13CyclicBarrier {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{
System.out.println("======召唤神龙");
});
for (int i = 1; i <= 14; i++) {
final int tempInt = i;
new Thread(()->{
try {
System.out.println(Thread.currentThread().getName() + "\t收集到第" + tempInt + "颗龙珠");
cyclicBarrier.await();
System.out.println(Thread.currentThread().getName() + "\t第" + tempInt + "颗龙珠飞走了");
} catch (Exception e) {
e.printStackTrace();
}
}, "Thread-"+String.valueOf(i)).start();
}
}
}
CyclicBarrier和CountDownLatch区别:
Condition接口(条件对象)
import java.util.Collections;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 案例:Tony仨小哥洗剪吹
* 演示多线程之间按顺序调用,实现A->B->C
* 三个线程Tony要求如下:
* tony雄雄-洗头,tony超超-理发,tony麦麦-吹干
* 。。。
* tony雄雄-洗头,tony超超-理发,tony麦麦-吹干
* 依次来10轮
*/
public class Demo14ConditionDemo {
public static void main(String[] args) {
ShareData shareData = new ShareData();
new Thread(()->{
for (int i = 0; i < 10; i++) {
shareData.wash();
}
}, "tony-雄雄").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
shareData.cut();
}
}, "tony-超超").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
shareData.cook();
}
}, "tony-麦麦").start();
}
}
class ShareData {
private volatile int number = 1; //tony-雄雄:1, tony-超超:2, tony-麦麦:3
private Lock lock = new ReentrantLock();
private Condition c1 = lock.newCondition(); //number == 1
private Condition c2 = lock.newCondition(); //number == 2
private Condition c3 = lock.newCondition(); //number == 3
/**
* A线程每一轮要执行的操作
*/
public void wash() {
lock.lock();
try{
//判断
while(number != 1){
c1.await();//阻塞
}
//模拟线程执行的任务
System.out.println(Thread.currentThread().getName()+"-洗头");
//通知
number = 2;
c2.signal();//唤醒了超超
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
/**
* B线程每一轮要执行的操作
*/
public void cut() {
lock.lock();
try{
//判断
while(number != 2){
c2.await();//阻塞
}
//模拟线程执行的任务
System.out.println(Thread.currentThread().getName()+"-理发");
//通知
number = 3;
c3.signal();//唤醒3
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void cook() {
lock.lock();
try{
//判断
while(number != 3){
c3.await();
}
//模拟线程执行的任务
System.out.println(Thread.currentThread().getName()+"-吹干");
//通知
number = 1;
c1.signal();//唤醒雄雄
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}