java并发编程:Semaphore使用信号量控制对资源的N个副本的并发访问
程序员文章站
2022-07-10 18:31:29
Semaphore的DEMO,使用信号量控制对N个副本的并发访问。...
目录
Semaphore:
这是一个计数器,用来控制N个共享资源的访问,这是一种基本的并发编程工具。
主程序:
该DEMO模拟20个任务,共享3个打印机的过程。并使其有序使用打印机。
package xyz.jangle.thread.test.n3_2.semaphore;
/**
* Semaphore DEMO 使用信号量控制对资源的N个副本的并发访问
* 该DEMO模拟20个任务,共享3个打印机的过程。并使其有序使用打印机。
*
* Semaphore的功能类型的同步锁的机制,但其区别是,其并发执行的数量并不限制为1个线程。
* 由 new Semaphore(3)参数3进行设置同步数量。
* 由 semaphore.acquire()来进行获取,acquire(2)可获取2个信号量。
* 由 semaphore.release()来进行释放,release(2)可释放2个信号量。
*
*
* @author jangle
* @email jangle@jangle.xyz
* @time 2020年8月8日 下午4:47:53
*
*/
public class M {
public static void main(String[] args) {
PrintQueue printQueue = new PrintQueue();
for (int i = 0; i < 20; i++) {
createThread(printQueue, i).start();
}
}
/**
* 创建线程
*
* @author jangle
* @time 2020年8月8日 下午5:21:23
* @param printQueue
* @return
*/
private static Thread createThread(PrintQueue printQueue, int i) {
return new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "开始执行");
printQueue.printJob(new Object());
System.out.println(Thread.currentThread().getName() + "完成执行");
}, "Thread" + i);
}
}
打印机组:
模拟3台打印机,对外提供服务。
package xyz.jangle.thread.test.n3_2.semaphore;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 模拟3台打印机进行对外服务
* @author jangle
* @email jangle@jangle.xyz
* @time 2020年8月8日 下午4:52:28
*
*/
public class PrintQueue {
// 信号量控制
private final Semaphore semaphore;
// 打印机组
private final boolean freePrintes[];
// 对获取打印机时,进行同步控制。
private final Lock lockPrinters;
public PrintQueue() {
super();
this.semaphore = new Semaphore(3);
this.freePrintes = new boolean[3];
for (int i = 0; i < freePrintes.length; i++) {
freePrintes[i] = true;
}
this.lockPrinters = new ReentrantLock();
}
/**
* 主要功能,使用信号量对现有打印机资源进行控制
*
* @author jangle
* @time 2020年8月8日 下午4:57:30
* @param document
*/
public void printJob(Object document) {
try {
// 获取访问许可(信号量)
semaphore.acquire();
int assignedPrinter = getPrinter();
System.out.println("模拟打印... 打印机编号" + assignedPrinter + "。当前线程" + Thread.currentThread().getName());
TimeUnit.SECONDS.sleep((long) (Math.random() * 10));
freePrintes[assignedPrinter] = true;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// 释放许可(信号量)
semaphore.release();
}
}
/**
* 获取打印机
*
* @author jangle
* @time 2020年8月8日 下午5:18:20
* @return
*/
private int getPrinter() {
// 用于保存打印机编号
int ret = -1;
try {
lockPrinters.lock();
for (int i = 0; i < freePrintes.length; i++) {
if (freePrintes[i]) {
ret = i;
freePrintes[i] = false;
break;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lockPrinters.unlock();
}
return ret;
}
}
执行结果:
Thread2开始执行
Thread5开始执行
Thread4开始执行
模拟打印... 打印机编号0。当前线程Thread2
模拟打印... 打印机编号2。当前线程Thread4
Thread3开始执行
Thread12开始执行
Thread0开始执行
Thread1开始执行
Thread13开始执行
Thread8开始执行
Thread7开始执行
Thread9开始执行
Thread10开始执行
模拟打印... 打印机编号1。当前线程Thread5
Thread6开始执行
Thread14开始执行
Thread16开始执行
Thread17开始执行
Thread19开始执行
Thread18开始执行
Thread15开始执行
Thread11开始执行
Thread5完成执行
模拟打印... 打印机编号1。当前线程Thread3
Thread3完成执行
模拟打印... 打印机编号1。当前线程Thread0
Thread2完成执行
模拟打印... 打印机编号0。当前线程Thread12
Thread0完成执行
模拟打印... 打印机编号1。当前线程Thread1
Thread4完成执行
模拟打印... 打印机编号2。当前线程Thread13
Thread12完成执行
模拟打印... 打印机编号0。当前线程Thread8
Thread13完成执行
模拟打印... 打印机编号2。当前线程Thread7
Thread7完成执行
模拟打印... 打印机编号2。当前线程Thread9
Thread1完成执行
模拟打印... 打印机编号1。当前线程Thread10
Thread8完成执行
模拟打印... 打印机编号0。当前线程Thread6
Thread10完成执行
模拟打印... 打印机编号1。当前线程Thread14
Thread6完成执行
模拟打印... 打印机编号0。当前线程Thread16
Thread14完成执行
模拟打印... 打印机编号1。当前线程Thread17
Thread9完成执行
模拟打印... 打印机编号2。当前线程Thread19
Thread17完成执行
模拟打印... 打印机编号1。当前线程Thread18
Thread16完成执行
模拟打印... 打印机编号0。当前线程Thread15
Thread19完成执行
模拟打印... 打印机编号2。当前线程Thread11
Thread18完成执行
Thread11完成执行
Thread15完成执行
本文地址:https://blog.csdn.net/Bof_jangle/article/details/107883239