App下載

Java并發(fā)編程中的Semaphore是什么?具體是怎么使用

閃耀旳白夢 2021-08-09 14:48:09 瀏覽數(shù) (1968)
反饋

簡介

Semaphore是用來限制訪問特定資源的并發(fā)線程的數(shù)量,相對于內(nèi)置鎖synchronized和重入鎖ReentrantLock的互斥性來說,Semaphore可以允許多個線程同時訪問共享資源。

Semaphored的使用

構(gòu)造方法

Semaphore(int permits):創(chuàng)建Semaphore,并指定許可證的數(shù)量。(公平策略為非公平)

Semaphore(int permits, boolean fair):創(chuàng)建Semaphore,并指定許可證的數(shù)量和公平策略。

核心方法

acquire():從Semaphore中獲取一個許可證,如果獲取不到則阻塞等待,直到其他線程釋放了一個許可證或者當前線程被中斷。

acquire(int permits):從Semaphore中獲取指定數(shù)量的許可證,如果獲取不到則阻塞等待,直到其他線程釋放了對應(yīng)數(shù)量的許可證或者當前線程被中斷。

acquireUninterruptibly():從Semaphore中獲取一個許可證,如果獲取不到則阻塞等待,直到其他線程釋放了一個許可證。(不響應(yīng)中斷)

tryAcquire():嘗試從Semaphore中獲取一個許可證,獲取成功則返回true,獲取失敗則返回false,不會進行等待。(不受公平策略的影響,許可證可用則立即獲得)

tryAcquire(long timeout, TimeUnit unit):嘗試從Semaphore中獲取一個許可證,獲取成功則返回true,獲取失敗則等待指定的時間,直到等待時間結(jié)束還是沒有獲取到許可證則返回false。

release():釋放一個許可證。

release(int permits):釋放指定數(shù)量的許可證。

示例

總共有5個許可證,最先獲取到許可證的5個線程開始執(zhí)行任務(wù),沒獲取到的線程進入等待狀態(tài),直到獲取到許可證的線程釋放許可證后,再獲取許可證執(zhí)行任務(wù)。

public class Demo {

    public static void main(String[] args) {
        //創(chuàng)建許可證數(shù)量為5的Semaphore
        Semaphore semaphore = new Semaphore(5);

        Runnable runnable = () -> {
            String threadName = Thread.currentThread().getName();
            try{
                //獲取一個許可證
                semaphore.acquire();
                System.out.println(threadName + "執(zhí)行任務(wù)...");
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                //釋放一個許可證
                semaphore.release();
            }
        };

        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for(int i = 0; i < 10; i++){
            executorService.execute(runnable);
        }

        executorService.shutdown();
    }

}

/* 開始輸出:
 * pool-1-thread-1執(zhí)行任務(wù)...
 * pool-1-thread-5執(zhí)行任務(wù)...
 * pool-1-thread-6執(zhí)行任務(wù)...
 * pool-1-thread-7執(zhí)行任務(wù)...
 * pool-1-thread-3執(zhí)行任務(wù)...
 * 三秒后輸出:
 * pool-1-thread-4執(zhí)行任務(wù)...
 * pool-1-thread-8執(zhí)行任務(wù)...
 * pool-1-thread-2執(zhí)行任務(wù)...
 * pool-1-thread-10執(zhí)行任務(wù)...
 * pool-1-thread-9執(zhí)行任務(wù)...
 */

使用Semaphore實現(xiàn)互斥

使用Semaphore實現(xiàn)互斥只需要將許可證數(shù)量設(shè)置為1,這樣就可以保證只有一個線程能獲取到許可證。

Semaphore semaphore = new Semaphore(1);

相比內(nèi)置鎖synchronized和重入鎖ReentrantLock,使用Semaphore實現(xiàn)互斥有個明顯的缺點:不可重入,沒有釋放許可證的情況下,再次調(diào)acquire方法將導(dǎo)致死鎖。

示例:

public class Demo {

    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(1);

        Runnable runnable = () -> {
            String threadName = Thread.currentThread().getName();
            try {
                //獲取一個許可證
                semaphore.acquire();
                System.out.println(threadName + "執(zhí)行任務(wù)A...");
                semaphore.acquire();
                System.out.println(threadName + "執(zhí)行任務(wù)B...");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                //釋放一個許可證
                semaphore.release();
            }
        };

        new Thread(runnable).start();
    }

}

/*
 * 輸出結(jié)果:
 * Thread-0執(zhí)行任務(wù)A...
 */

“執(zhí)行任務(wù)B”永遠不會打印,因為許可證只有一個,第二次acquire方法的調(diào)用會因為無法獲取到許可證而一直阻塞。

以上就是Java并發(fā)編程之Semaphore的使用簡介的詳細內(nèi)容,想要了解更多關(guān)于Java并發(fā)編程中Semaphore的其他資料,請關(guān)注W3Cschool其它相關(guān)文章!

0 人點贊