天天看点

java semaphore

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[];

        for (int i=; i<; i++) {
            thread[i] = new Thread(new Job(pq), "Thread" + i);
        }

        for (int i=; i<; i++) {
            thread[i].start();
        }
    }
}

class PrintQueue {
    private final Semaphore semaphore;

    public PrintQueue() {
        semaphore = new Semaphore();
    }

    public void printJob(Object doc) {
        try {
            semaphore.acquire();
            long duration = (long) (Math.random()*);
            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();

        freePrinters = new boolean[];
        for (int i = ; i < ; i++) {
            freePrinters[i] = true;
        }
        lockPrinter = new ReentrantLock();
    }

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

            int assignedPrinter = getPrinter();

            long duration = (long) (Math.random()*);
            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 = -;
        try {
            lockPrinter.lock();
            for (int i=; 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());
    }

}
           

继续阅读