java semaphore
JAvaはsemaphore方式に基づいてリソースへの同時アクセスを実現し、マルチスレッド同期の一種でもある.一般的には複数のリソースコピーへの同時アクセス制御を実現するために用いられるが、synchronized、lockなどの同期方式は1つのリソースに対する同時アクセス制御に用いられる.つまり、リソースは1つのスレッドのみが同時にアクセスできる.semaphoreは、いくつかのスレッドを制御してリソースに同時にアクセスできます.もちろんsemaphoreにも変種があります.すなわち、バイナリ信号量です.実際にはsynchronizedとlockと差が少なく、バイナリ信号量もリソースが1つのスレッドだけで同時にアクセスできることを制限します.具体的な内容は以下の例を参考にすることができる.
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
",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
",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; iif (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
",Thread. currentThread().getName());
printQueue.printJob(new Object());
System.out.printf("%s: The document has been printed
",Thread.currentThread().getName());
}
}