Java併發編程中級篇(一):使用Semaphore信號量進行併發控制

Semaphore是一個二進制信號量,只有0和1兩個值。若是線程想要訪問一個共享資源,它必須先得到信號量。若是信號量的內部計數器大於0,那麼信號量減1,並容許訪問這個資源。不然,若是信號量計數器等於0,線程會等待直至計數器大於0。java

因此說計數器大於0,說明有資源可用。計數器等於0,說明沒有資源可用。併發

同時Semaphore提供了一個帶有boolean參數的構造方法,true表明公平鎖,false表明非公平鎖,默認實現是非公平鎖。dom

咱們使用Semaphore信號量來重寫PrintQueue的例子。ide

首先實現一個PrintQueue打印隊列,有一個Semaphore信號量用來併發訪問控制。打印以前使用acquire()方法獲取信號量,執行完畢後使用release()方法釋放信號量。每次打印等待一個隨機時間,模擬打印耗時。ui

public class PrintQueue {
    private Semaphore semaphore;

    public PrintQueue() {
        //semaphore = new Semaphore(1);   //非公平的
        semaphore = new Semaphore(1, true); //公平的
    }

    public void printJob(Object document) {
        try {
            semaphore.acquire();
            long duration = (long)(Math.random() * 10000);
            System.out.printf("%s: Print a job duration %d seconds.\n",
                    Thread.currentThread().getName(), duration / 1000);
            Thread.sleep(duration);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            semaphore.release();
        }
    }
}

建立Job線程類,模擬打印請求。this

public class Job implements Runnable{
    private PrintQueue printQueue;

    public Job(PrintQueue printQueue) {
        this.printQueue = printQueue;
    }

    @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 Job has been printed.\n", Thread.currentThread().getName());
    }
}

主方法類中啓動10個打印Job線程。線程

public class Main {
    public static void main(String[] args) {
        PrintQueue printQueue = new PrintQueue();

        Thread[] threads = new Thread[10];
        for (int i = 1; i < 10; i++) {
            threads[i] = new Thread(new Job(printQueue));
        }

        for (int i = 1; i < 10; i++) {
            threads[i].start();
        }
    }
}

查看日誌,每次只有一個打印Job能夠執行打印程序,其餘線程處於WAITING狀態。日誌

Thread-0: Going to print a Job.
Thread-8: Going to print a Job.
Thread-7: Going to print a Job.
Thread-6: Going to print a Job.
Thread-5: Going to print a Job.
Thread-4: Going to print a Job.
Thread-0: Print a job duration 2 seconds.
Thread-3: Going to print a Job.
Thread-2: Going to print a Job.
Thread-1: Going to print a Job.
Thread-0: The Job has been printed.
Thread-8: Print a job duration 8 seconds.
Thread-8: The Job has been printed.
Thread-7: Print a job duration 8 seconds.
Thread-7: The Job has been printed.
Thread-6: Print a job duration 9 seconds.
Thread-6: The Job has been printed.
Thread-5: Print a job duration 6 seconds.
Thread-5: The Job has been printed.
Thread-4: Print a job duration 7 seconds.
Thread-4: The Job has been printed.
Thread-3: Print a job duration 4 seconds.
Thread-3: The Job has been printed.
Thread-2: Print a job duration 1 seconds.
Thread-2: The Job has been printed.
Thread-1: Print a job duration 1 seconds.
Thread-1: The Job has been printed.
相關文章
相關標籤/搜索