日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

Java线程并发常用工具类使用

發(fā)布時(shí)間:2025/3/11 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java线程并发常用工具类使用 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

這次整理了一些比較常用的線程工具類啦。

CountDownLatch:在一組線程執(zhí)行完后,才能開始執(zhí)行調(diào)用等待的線程。上片文章提到過junit的測(cè)試盡量不要測(cè)試線程,如果硬是要可以使用CountDownLatch進(jìn)行測(cè)試

CyclicBarrier:在一組線程中調(diào)用等待方法后,只有這組所有線程都進(jìn)入等待后,會(huì)執(zhí)行一個(gè)指定的線程,在指定的線程執(zhí)行完后,這組等待的線程才能繼續(xù)執(zhí)行。

Semaphore:可用于限流使用。

Exchanger:當(dāng)兩組線程都執(zhí)行到交換的方法時(shí),能將數(shù)據(jù)在這兩個(gè)線程之間進(jìn)行數(shù)據(jù)交換。

CountDownLatch

該類實(shí)現(xiàn)主要是由一個(gè)內(nèi)部類Sync實(shí)現(xiàn)的,Sync繼承了AbstractQueuedSynchronizer(就是經(jīng)常提到的AQS),

常用的方法有兩個(gè):

1.await():線程調(diào)用該方法進(jìn)入帶阻塞狀態(tài),只有當(dāng)調(diào)用countDown()并驟減到0的時(shí)候,才能繼續(xù)執(zhí)行

2.countDown():線程驟減一個(gè)單位。

具體實(shí)現(xiàn):

?

public class CountDownLatchMain {static CountDownLatch latch = new CountDownLatch(6);static class InitThread implements Runnable{public void run() {try {TimeUnit.MILLISECONDS.sleep(200L);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println("Thread name:"+Thread.currentThread().getName()+" init ...");latch.countDown();}}static class BusinessThread implements Runnable{public void run() {try {latch.await();} catch (InterruptedException e1) {e1.printStackTrace();}for(int i=0;i<3;i++) {try {TimeUnit.MILLISECONDS.sleep(100L);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Thread name : " + Thread.currentThread().getName()+" work_" + i);}}}public static void main(String[] args) throws InterruptedException {new Thread(new Runnable() {public void run() {latch.countDown();System.out.println("thread name "+Thread.currentThread().getName()+" 1st init ...");try {TimeUnit.MILLISECONDS.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}latch.countDown();System.out.println("thread name "+Thread.currentThread().getName()+" 2nd init ...");}},"Thread-0").start();new Thread(new BusinessThread()).start();for(int i=0;i<=4 ;i++) {new Thread(new InitThread()).start();}latch.await();TimeUnit.MILLISECONDS.sleep(300);System.out.println("main end ...");} }

?執(zhí)行結(jié)果:

thread name Thread-0 1st init ... Thread name:Thread-1 init ... Thread name:Thread-3 init ... Thread name:Thread-2 init ... Thread name:Thread-5 init ... Thread name:Thread-4 init ... Thread name : Thread-0 work_0 Thread name : Thread-0 work_1 Thread name : Thread-0 work_2 main end ... thread name Thread-0 2nd init ...

CyclicBarrier

?

與CountDownLatch差不多,都是等待線程執(zhí)行完后,才能繼續(xù)執(zhí)行,不過這兩個(gè)不同的地方就是:CountDownLatch需要手動(dòng)在邏輯代碼中進(jìn)行驟減,減到臨界點(diǎn)后,阻塞的線程會(huì)繼續(xù)執(zhí)行,而CountDownLatch是一組線程都進(jìn)入到阻塞狀態(tài)后,然后執(zhí)行指定線程執(zhí)行完后,那組阻塞的線程才能繼續(xù)執(zhí)行。 示例:

public class CyclicBarrierMain {static CyclicBarrier barrier = new CyclicBarrier(5,new Runnable() {public void run() {System.out.println("Thread name : " + Thread.currentThread().getName() + " barrier start...");try {TimeUnit.MILLISECONDS.sleep(100L);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println("Thread name : " + Thread.currentThread().getName() + " barrier thread ...");}});static class SubThread implements Runnable{public void run() {long sleep = (long) (Math.random()*1000);System.out.println("thread name : " + Thread.currentThread().getName() + " init ...");try {TimeUnit.MILLISECONDS.sleep(sleep);} catch (InterruptedException e) {e.printStackTrace();}try {System.out.println("thread name : " + Thread.currentThread().getName() + " sleep time:"+sleep);barrier.await();} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}System.out.println("thread name : " + Thread.currentThread().getName() + " end ....");}}public static void main(String[] args) {for(int i =0 ; i<5;i++) {new Thread(new SubThread()).start();}} }

執(zhí)行結(jié)果:

thread name : Thread-2 init ... thread name : Thread-4 init ... thread name : Thread-1 init ... thread name : Thread-0 init ... thread name : Thread-3 init ... thread name : Thread-2 sleep time:405 thread name : Thread-0 sleep time:488 thread name : Thread-1 sleep time:564 thread name : Thread-4 sleep time:777 thread name : Thread-3 sleep time:860 Thread name : Thread-3 barrier start... Thread name : Thread-3 barrier thread ... thread name : Thread-3 end .... thread name : Thread-2 end .... thread name : Thread-1 end .... thread name : Thread-0 end .... thread name : Thread-4 end ....

Semaphore

?

主要用于需要做限制的場(chǎng)景,比如限制連接池獲取次數(shù)等等,也有一個(gè)Sync內(nèi)部類繼承了AQS

常用方法:

1、acquire():驟減一個(gè)單位,也可調(diào)用帶參的方法可指定減值,當(dāng)驟減到0的時(shí)候,調(diào)用該方法會(huì)進(jìn)入阻塞狀態(tài)。

2、release():釋放一個(gè)單位,也會(huì)在初始化的數(shù)量進(jìn)行增加。

3、availablePermits():得到可獲取單位的數(shù)量。

4、getQueueLength():調(diào)用了acquire()方法并進(jìn)入到阻塞狀態(tài)的總數(shù)量。

具體用法:

Semaphore semaphore = new Semaphore(5); semaphore.acquire();//也可指定減少多個(gè)semaphore.acquire(2); //...第6個(gè)acquire()方法時(shí),再次調(diào)用將進(jìn)入等待,直到在某個(gè)線程中執(zhí)行了semaphore.release()方法才會(huì)繼續(xù)執(zhí)行后面的 //...

Exchanger

主要用于兩個(gè)線程之間的數(shù)據(jù)交換,個(gè)人覺得這個(gè)用處不大,既然看到了這個(gè),也就順便整理了一下

使用示例:

public class UseExcahnger {static Exchanger<Set<String>> exchanger = new Exchanger<Set<String>>();static class ThreadOne extends Thread{@Overridepublic void run() {Set<String> set = new HashSet<String>();set.add("1");set.add("2");try {System.out.println(Thread.currentThread().getName() + " > set:" + set);Thread.sleep(2000L);Set<String> exchange = exchanger.exchange(set);System.out.println(Thread.currentThread().getName() + " > " + exchange);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}static class ThreadTwo extends Thread{@Overridepublic void run() {Set<String> set = new HashSet<String>();set.add("3");set.add("4");try {System.out.println(Thread.currentThread().getName() + " > set:" + set);Thread.sleep(3000L);Set<String> exchange = exchanger.exchange(set);System.out.println(Thread.currentThread().getName() + " > " + exchange);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}public static void main(String[] args) {new ThreadOne().start();new ThreadTwo().start();} }

執(zhí)行結(jié)果為:

Thread-0 > set:[1, 2] Thread-1 > set:[3, 4] Thread-1 > [1, 2] Thread-0 > [3, 4]

Future/FutureTask

這個(gè)在之前的提到過,與Callable一起使用,用來做回調(diào)的,個(gè)人覺得這個(gè)與之前的Fork/Join的分而治之有些相似,都是異步同時(shí)執(zhí)行完后將結(jié)果返回,然后發(fā)現(xiàn)相似之后,回去看了一下源代碼

RecursiveActionRecursiveTask<T>?都分別繼承了Future接口,而FutureTask也繼承了Future、Runnable,所以FutureTask既能作為Callable帶有返回結(jié)果,也能作為Thread去執(zhí)行它。

這里就介紹一下類中的一些方法,示例的話可以翻看之前的文章

1、isDone():判斷線程是否已結(jié)束。

2、boolean cancel(boolean mayInterruptIfRunning):參數(shù)為true是中斷線程,但是只會(huì)發(fā)送中斷信號(hào),在程序中需要自行判斷,參數(shù)為false則不會(huì)中斷,返回值為true,如果線程已結(jié)束或未開始則返回false。

3、isCancelled():判斷線程是否關(guān)閉。

4、get():獲取線程返回值。

好啦,就先整理這些啦,后面還有一些還在整理,后期會(huì)繼續(xù)分享的呀,如果有問題煩請(qǐng)各路大佬指出

?

?

?

總結(jié)

以上是生活随笔為你收集整理的Java线程并发常用工具类使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。