Java并發(fā)編程信號量Semapher
Semapher
信號量也是Java中的一個同步器,與CountDownLatch和CycleBarrier不同的是,它內部的計數器是遞增的,并且在一開始初始化Semaphoer時可以指定一個初始值,但是并不需要知道需要同步的線程個數,而是在需要同步的地方調用acquire方法時指定需要同步的線程個數。
我們通過下面一個例子來看一下Semapher效果:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; public class SemaphoreTest { private static Semaphore semaphore = new Semaphore(0); public static void main(String[] args) throws InterruptedException{ ExecutorService executorService = Executors.newFixedThreadPool(2); executorService.submit(new Runnable() { @Override public void run() { try { System.out.println(Thread.currentThread() + "over"); semaphore.release(); } catch (Exception e) { e.printStackTrace(); } } }); executorService.submit(new Runnable() { @Override public void run() { try { System.out.println(Thread.currentThread() + "over"); semaphore.release(); } catch (Exception e) { e.printStackTrace(); } } }); semaphore.acquire(2); System.out.println("all child thread over!"); executorService.shutdown(); } }
如上代碼首先創(chuàng)建了一個信號量實例,構造函數的入參為0,說明當前信號量計數器的值為0。然后,main函數向線程池添加兩個線程任務,在每個線程內部調用信號量的acquire方法,傳參為2說明調用acquire方法的線程會一直阻塞,知道信號量的技術變?yōu)?才會返回。如果構造Semaphore時,傳遞的參數為N,并在M個線程中調用了該信號量的release方法,那么在調用acquire使M個線程同步時傳遞的參數應該是M+N。
下面舉例子來模擬CycliBarrier復用的功能,代碼如下:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; public class Semaphoer { private static Semaphore semaphore = new Semaphore(0); public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newFixedThreadPool(2); executorService.submit(new Runnable() { @Override public void run() { try { System.out.println(Thread.currentThread() + "A task over"); semaphore.release(); } catch (Exception e) { e.printStackTrace(); } } }); executorService.submit(new Runnable() { @Override public void run() { try { System.out.println(Thread.currentThread() + "A task over"); semaphore.release(); } catch (Exception e) { e.printStackTrace(); } } }); semaphore.acquire(2); System.out.println("task A is over"); executorService.submit(new Runnable() { @Override public void run() { try { System.out.println(Thread.currentThread() + "B task over"); semaphore.release(); } catch (Exception e) { e.printStackTrace(); } } }); executorService.submit(new Runnable() { @Override public void run() { try { System.out.println(Thread.currentThread() + "B task over"); semaphore.release(); } catch (Exception e) { e.printStackTrace(); } } }); semaphore.acquire(2); System.out.println("task B is over"); executorService.shutdown(); } }
如上代碼首先將線程A和線程B加入到線程池。主線程執(zhí)行代碼(1)后被阻塞。線程A和線程B調用release
方法后信號量的值變?yōu)榱?,這時候主線程的aquire方法會在獲取到2個信號量后返回(返回后當前信號量值為0)。然后主線程添加線程C和線程D到線程池,之后主線程執(zhí)行代碼(2)后被阻塞(因為主線程要獲取2個信號量,而當前信號量個數為0)。當線程C和線程D執(zhí)行完release 方法后,主線程才返回。從本例子可以看出,Semaphore
在某種程度上實現(xiàn)了CyclicBarrier 的復用功能。
到此這篇關于Java并發(fā)編程信號量Semapher的文章就介紹到這了,更多相關Java Semapher內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
使用SpringBoot實現(xiàn)微服務超時重試模式的示例
這篇文章主要介紹了使用SpringBoot實現(xiàn)微服務超時重試模式的示例,幫助大家更好的理解和使用springboot框架,感興趣的朋友可以了解下2020-11-11java通過URLClassLoader類加載器加載外部jar代碼示例
ClassLoader翻譯過來就是類加載器,普通的java開發(fā)者其實用到的不多,但對于某些框架開發(fā)者來說卻非常常見,下面這篇文章主要給大家介紹了關于java通過URLClassLoader類加載器加載外部jar的相關資料,需要的朋友可以參考下2024-01-01關于Jackson的JSON工具類封裝 JsonUtils用法
這篇文章主要介紹了關于Jackson的JSON工具類封裝 JsonUtils用法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09SpringSecurity實現(xiàn)動態(tài)url攔截(基于rbac模型)
本文主要介紹了SpringSecurity動態(tài)url攔截,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-08-08