线程协作工具类【CountDownLatch倒数门闩、Semaphore信号量、CyclicBarrier循环栏栅、Condition接口】
线程协作工具类
- CountDownLatch倒数门闩
- Semaphore信号量
- CyclicBarrier循环栅栏
- CyclicBarrier和CountDownLatch区别:
- Condition接口(条件对象)
转自 极客时间
线程协作工具类就是帮助程序员更容易的让线程之间进行协作,来完成某个业务功能。
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-麦麦:3private Lock lock = new ReentrantLock();private Condition c1 = lock.newCondition(); //number == 1private Condition c2 = lock.newCondition(); //number == 2private 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();}}
}