Bootstrap

java.util.concurrent|Semaphore使用

Semaphore是java.util.concurrent中的一个类,翻译成中文是“信号量”,它是一个计数器,使用场景基本上多线程访问共享资源,保护共享资源在某个时间只能被一个线程使用。

Semaphore原理

Semaphore相当于计数器,它可以增加,也可以减少,在初始化对象的时候,可以指定permits(信号量)数目,比如5,那么,Semaphore最多减少到0,最多增加不超过5。
显然,Semaphore更多时候被当作计数器来使用,当计数器为0的时候,线程处于等待状态,因此,它可以当作锁来使用。
在多线程编程中,使用Semaphore保护共享资源,一定要在线程中使用semaphore的acquire方法获取“信号量”,如果信号量大于0就可以使用共享资源,等于0则使用线程处于等待状态,直到其他线程使用完资源后调用release释放“信号量”

Semaphore使用

场景:使用Semaphore保证打印任务只能被多线程中的一个使用

PrintingJob.java
/**
 * 提交任务给打印队列
 * @Auothor wzx
 * @Date 2017/3/11 0011
 */
public class PrintingJob implements Runnable {

    private PrinterQueue printerQueue;

    public PrintingJob(PrinterQueue printerQueue) {
        this.printerQueue = printerQueue;
    }

    @Override
    public void run() {
        System.out.printf("%s: Going to print a document\n", Thread.currentThread().getName());
        printerQueue.printJob(new Object());
    }

}
PrinterQueue.java
/**
 * 打印任务,使用semaphore保证
 * @Auothor wzx
 * @Date 2017/3/11 0011
 */
public class PrinterQueue {

    private final Semaphore semaphore;


    public PrinterQueue() {
        this.semaphore = new Semaphore(1);
    }

    public void printJob(Object document) {
        try {
           semaphore.acquire();

            long duration = (long) (Math.random() * 10000);
            System.out.println(Thread.currentThread().getName() + ": PrintQueue: Printing a Job during " +
                    (duration/1000) + " seconds :: Time - " + new Date());
            Thread.sleep(duration);

        } catch(InterruptedException e) {
            e.printStackTrace();
        } finally {
            System.out.printf("%s The document has been printed\n", Thread.currentThread().getName());
            semaphore.release();
        }
    }

}
SemaphoreExample .java
/**
 * 测试Semaphore
 * @Auothor wzx
 * @Date 2017/3/11 0011
 */
public class SemaphoreExample {

    public static void main(String[] args) {
        PrinterQueue printerQueue = new PrinterQueue();
        Thread[] threads = new Thread[10];
        for (int i = 0; i < 10; i++) {
            threads[i] = new Thread(new PrintingJob(printerQueue));
        }
        for (int i = 0; i < 10; i++) {
            threads[i].start();
        }
    }
}

输出如下:

Thread-0: Going to print a document
Thread-9: Going to print a document
Thread-8: Going to print a document
Thread-7: Going to print a document
Thread-6: Going to print a document
Thread-5: Going to print a document
Thread-4: Going to print a document
Thread-3: Going to print a document
Thread-2: Going to print a document
Thread-1: Going to print a document
Thread-0: PrintQueue: Printing a Job during 3 seconds :: Time - Sat Mar 11 20:01:40 CST 2017
Thread-0 The document has been printed
Thread-9: PrintQueue: Printing a Job during 3 seconds :: Time - Sat Mar 11 20:01:44 CST 2017
Thread-9 The document has been printed
Thread-8: PrintQueue: Printing a Job during 9 seconds :: Time - Sat Mar 11 20:01:47 CST 2017
Thread-8 The document has been printed
Thread-7: PrintQueue: Printing a Job during 5 seconds :: Time - Sat Mar 11 20:01:56 CST 2017
Thread-7 The document has been printed
Thread-6: PrintQueue: Printing a Job during 9 seconds :: Time - Sat Mar 11 20:02:01 CST 2017
Thread-6 The document has been printed
Thread-5: PrintQueue: Printing a Job during 9 seconds :: Time - Sat Mar 11 20:02:11 CST 2017
Thread-5 The document has been printed
Thread-4: PrintQueue: Printing a Job during 4 seconds :: Time - Sat Mar 11 20:02:21 CST 2017
Thread-4 The document has been printed
Thread-3: PrintQueue: Printing a Job during 3 seconds :: Time - Sat Mar 11 20:02:25 CST 2017
Thread-3 The document has been printed
Thread-2: PrintQueue: Printing a Job during 5 seconds :: Time - Sat Mar 11 20:02:28 CST 2017
Thread-2 The document has been printed
Thread-1: PrintQueue: Printing a Job during 6 seconds :: Time - Sat Mar 11 20:02:34 CST 2017
Thread-1 The document has been printed

使用步骤:
1.使用acquire()方法获取“信号量”;
2.对共享资源进行操作;
3.使用release()方法释放资源,为保证资源能安全释放,推荐写在finally代码块中;

参考
http://howtodoinjava.com/core-java/multi-threading/binary-semaphore-tutorial-and-example/

;