java基于semaphore方式实现对资源的并发访问,也是多线程同步的一种方式,它一般是用于实现对多个资源副本的并发访问控制,而synchronized,lock等同步方式不同则用于针对一个资源的并发访问控制,也就是说资源只允许一个线程同时访问,而semaphore则可以控制某几个线程同时访问资源。
当然semaphore它也有一个变种,即二进制信号量,它的作用实际上和synchronized和lock就差不多了,二进制信号量也是限制资源只允许一个线程同时访问。
具体的内容可以参考下面的例子。
package com.basic.thread;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class BasicSemaphore {
public static void main(String args[]) {
PrintQueueSem pq = new PrintQueueSem();
Thread thread[] = new Thread[10];
for (int i=0; i<10; i++) {
thread[i] = new Thread(new Job(pq), "Thread" + i);
}
for (int i=0; i<10; i++) {
thread[i].start();
}
}
}
class PrintQueue {
private final Semaphore semaphore;
public PrintQueue() {
semaphore = new Semaphore(1);
}
public void printJob(Object doc) {
try {
semaphore.acquire();
long duration = (long) (Math.random()*10);
System.out.printf("%s: PrintQueue: Printing a Job during %d seconds\n",Thread.currentThread().getName(),duration);
Thread.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}
}
class PrintQueueSem {
private boolean freePrinters[];
private Lock lockPrinter;
private final Semaphore semaphore;
public PrintQueueSem() {
semaphore = new Semaphore(3);
freePrinters = new boolean[3];
for (int i = 0; i < 3; i++) {
freePrinters[i] = true;
}
lockPrinter = new ReentrantLock();
}
public void printJob(Object obj) {
try {
semaphore.acquire();
int assignedPrinter = getPrinter();
long duration = (long) (Math.random()*10);
System.out.printf("%s: PrintQueue: Printing a Job in Printer%d during %d seconds\n",Thread.currentThread().getName(), assignedPrinter,duration);
Thread.sleep(duration);
freePrinters[assignedPrinter] = true;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}
private int getPrinter() {
int ret = -1;
try {
lockPrinter.lock();
for (int i=0; i<freePrinters.length; i++) {
if (freePrinters[i]) {
ret = i;
freePrinters[i]=false;
break;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lockPrinter.unlock();
}
return ret;
}
}
class Job implements Runnable {
/**
private PrintQueue printQueue;
public Job(PrintQueueSem pq) {
this.printQueue = pq;
}
*/
private PrintQueueSem printQueue;
public Job(PrintQueueSem pq) {
this.printQueue = pq;
}
@Override
public void run() {
System.out.printf("%s: Going to print a job\n",Thread. currentThread().getName());
printQueue.printJob(new Object());
System.out.printf("%s: The document has been printed\n",Thread.currentThread().getName());
}
}