描述
本次自定义了一个实践内容,同时学习使用使用CountDownLatch,CyclicBarrier,Semaphore。
- 工厂进行生产和销售。
- 生产车间机器有限,使用需要排队。
主函数
// CountDownLatch:
// --> CountDownLatch(int count) , 等待count个线程结束,通过计数器方法判断线程执行完毕,之后继续向下执行。使用await()进行阻塞等待,线程结束后使用countDown() 对计数器进行-1操作。
// CyclicBarrier:
// --> CyclicBarrier(int parties),执行parties个任务,所有任务结束后,继续向下执行,和CountDownLatch类似,内部是加计数器,加到目标值认为任务完成,await()进行阻塞等待,自动计数。
// Semaphore:
// --> Semaphore(int permits),声明permits个资源,通过acquire获取一个资源,通过release释放一个资源,资源不够时,acquire会进行等待,直到获得资源,可以设置等待资源的超时时间。
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(1, new Runnable() {
@Override
public void run() {
System.out.println("卖光了,明天来吧!");
}
});
new DoRun(barrier).start();
}
static class DoRun extends Thread {
private CyclicBarrier barrier;
public DoRun(CyclicBarrier barrier){
this.barrier = barrier;
}
@Override
public void run() {
try {
System.out.println("开始运营啦..");
MachineFactoryImpl factory = new MachineFactoryImpl();
// 每天生产和销售的数量,自行进行设置
factory.production(10);
factory.consume(10);
barrier.await();
}catch (Exception e){
e.printStackTrace();
}
}
}
工厂
public class MachineFactoryImpl implements MachineFactory {
// 最大库存量(爆仓啦)
private final int MAX_STORAGE = 100;
// 仓库空间
private LinkedList list = new LinkedList();
@Override
public void production(int num) {
// 负责生产产品
// 生产前需要判断仓库满了没有,如果仓库放不下,则等待被消费后,满足空间条件再生产
// 生产时需要持有list的锁,避免因为同时生产和消费时,产生队列下标异常的错误。
synchronized (list){
while (list.size() + num > MAX_STORAGE){
System.out.println("【当前仓库库存量: "+list.size()+"】,【即将生产的货量: "+num+"】 等待仓库位置空间!");
try {
Thread.sleep(3000);
// 线程释放锁,进入等待状态
list.wait();
}catch (Exception e){
e.printStackTrace();
}
}
new WorkShop().doWork(num);
// 满足生产条件进行生产
for (int i = 0; i<num; i++){
list.add(new Object());
}
System.out.println("【生产的数量:"+num + "】"+"【当前仓库的库存:"+list.size() + "】");
// 此时可能存在消费者在等待工厂生产产品,所以要通知所有处于wait状态的消费线程
// 他们将收到状态改变的通知进行判断是否执行程序代码
list.notifyAll();
}
}
@Override
public void consume(int num) {
// 负责消费产品
// 消费的前提是拥有足够的产品,若是仓库不存在这么多的产品,则进行等待,直到有这么多的产品进行消费
synchronized (list){
while (list.size() < num){
System.out.println("【当前仓库库存量: "+list.size()+"】,【即将消费的数量: "+num+"】 等待工厂生产!");
try {
Thread.sleep(2000);
// 让出锁,进入等待状态
list.wait();
}catch (Exception e){
e.printStackTrace();
}
}
new Store().sell(num);
// 满足条件
for (int i = 0; i<num; i++){
list.remove();
}
System.out.println("【消耗的数量:"+num +"】,【当前仓库剩余:"+list.size() + "】");
// 此时仓库可能已经爆仓,需要通知生产线程进行过了一次消费,此时生产现场收到状态会进行重新的检查
list.notifyAll();
}
}
}
车间
public class WorkShop {
public void doWork(int val){
// 8台机器
int machine = 8;
//
try {
Semaphore semaphore = new Semaphore(machine);
CountDownLatch latch = new CountDownLatch(val);
for (int i=0;i<val;i++){
new Work(i,semaphore,latch).start();
}
latch.await();
}catch (Exception e){
e.printStackTrace();
}
System.out.println("零件生产完成!");
}
static class Work extends Thread {
private int work_no;
private Semaphore semaphore;
private CountDownLatch latch;
public Work(int no, Semaphore semaphore,CountDownLatch latch){
this.work_no = no;
this.semaphore = semaphore;
this.latch = latch;
}
@Override
public void run() {
try {
// 申请机器资源
semaphore.acquire();
System.out.println("工人编号:"+work_no+" 申请一台机器进行生产零件");
Thread.sleep(2000);
System.out.println("工人编号:"+work_no+" 生产完成,释放机器");
// 使用完毕释放机器资源
semaphore.release();
// 计数器-1
latch.countDown();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
商店
public class Store {
public void sell(int val){
// 销售val台设备,必须等待销售完成才继续采购
CountDownLatch latch = new CountDownLatch(val);
try {
for (int i=0;i<val;i++){
new DoSell(latch).start();
}
latch.await();
}catch (Exception e){
e.printStackTrace();
}
System.out.println("全部销售完成..");
}
static class DoSell extends Thread {
private CountDownLatch latch;
public DoSell(CountDownLatch latch){
this.latch = latch;
}
@Override
public void run() {
try {
System.out.println("开始进行销售...");
Random r = new Random();
// 随机时间销售出去,最长10秒
int mills = r.nextInt(10000);
Thread.sleep(mills);
System.out.println("成功销售一台设备!");
latch.countDown();
}catch (Exception e){
e.printStackTrace();
}
}
}
}