1. 程式人生 > >【執行緒】- JUC 4種執行緒同步工具

【執行緒】- JUC 4種執行緒同步工具

浪費了“黃金五年”的Java程式設計師,還有救嗎? >>>   

Semaphore:訊號燈

特點:控制每次執行的執行緒數,達到控制執行緒併發的效果

  • 測試程式碼
package com.zhiwei.thread;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

/**
 * 訊號燈:當執行緒空閒時自動去執行阻塞的執行緒,實現執行最優化
 */
public class SemaphoreTest {

public static void main(String[] args) {

    ExecutorService threadPool = Executors.newCachedThreadPool();

    // 定義訊號燈,一次最多能處理3個執行緒
    Semaphore sp = new Semaphore(3); 

    for (int i = 0; i < 20; i++) {
        threadPool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    
                    // 獲取訊號,訊號燈處理阻塞執行緒,最多允許3個執行緒訪問
                    sp.acquire(); 
                    
                    System.out.println(Thread.currentThread().getName() + ":進入訊號燈,還有" +  sp.availablePermits() + "個訊號");
                    
                    Thread.sleep(new Random().nextInt(2000));
                    
                    // 回收訊號燈訊號,供別的執行緒使用
                    sp.release();
                    System.out.println(Thread.currentThread().getName() + ":離開訊號燈,還有" +  sp.availablePermits() + "個訊號");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    }
    threadPool.shutdown();
}
}

效果:


CyclicBarrier

作用:控制執行緒執行的任務總量同步,例如等待所有人完成工作才可以下班

測試程式碼

package com.zhiwei.thread;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CyclicBarrierTest {

	public static void main(String[] args) {
		
    // 思想:只有各個子任務都完成了採取執行下一步,如果有執行緒提前完成則等待
    ExecutorService threadPool = Executors.newCachedThreadPool();
    
    // 規定總的任務量:只有全部完成才會進行下一步處理
    CyclicBarrier cb = new CyclicBarrier(3); 

    for (int i = 0; i < 3; i++) {
        threadPool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep((long) (Math.random() * 10000));
                    System.out.println(Thread.currentThread().getName() + ":完成分任務,剩餘任務:" + (2 - cb.getNumberWaiting()));
                    
                    //如果前面2個執行緒阻塞 + 正在執行的執行緒 = 3,表明總任務完成
                    if (cb.getNumberWaiting() == 2) {
                        System.out.println("恭喜,總任務已完成!");
                    }

                    //分任務完成則等待,直到搜尋的任務都完成,才執行await後面的程式碼
                    cb.await(); 
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    threadPool.shutdown();
}
}

效果:


CountDownLatch 發令槍

CountDownLatch:可理解為所有執行緒都就緒之後就一起執行,類似旅遊跟團,只有所有人都到了才可以觸發

測試程式碼

package com.zhiwei.thread;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CountDownLatchTest {

	public static void main(String[] args) {

    // 快取執行緒池:自動建立執行緒執行任務,如果執行緒執行完成任務則儲存,供下次使用,如果執行緒不夠則動態建立
    ExecutorService threadPool = Executors.newCachedThreadPool();

    // 表示將完成3個任務量:任務計數器:多執行緒完成一些列操作
    CountDownLatch ct = new CountDownLatch(3);

    for (int i = 0; i < 3; i++) {

        threadPool.execute(new Runnable() {
            @Override
            public void run() {
                try {

                    Thread.sleep((long) (Math.random() * 10000));
                    ct.countDown(); // 減1
 					System.out.println(Thread.currentThread().getName() + "準備分任務,剩餘任務:" + ct.getCount());
                   

                    // 如果ct計數器不為0則阻塞,為0 則一起執行
                    ct.await(); 
                     System.out.println(Thread.currentThread().getName() + "完成分任務");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
	if (ct.getCount() == 0) {
                        System.out.println("恭喜,總任務已完成!");
                    }
    threadPool.shutdown();
}
}

效果:


ArrayBlockingQueue

ArrayBlockingQueue: JDK內部提供的阻塞佇列,能夠保證執行緒安全

主要同步方法:

put方法

 public void put(E e) throws InterruptedException {
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == items.length)
                notFull.await();
            enqueue(e);
        } finally {
            lock.unlock();
        }
    }

take方法

 public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == 0)
                notEmpty.await();
            return dequeue();
        } finally {
            lock.unlock();
        }
    }

測試程式碼:

package com.zhiwei.thread;
import java.util.concurrent.ArrayBlockingQueue;

/**
 * 阻塞佇列:可用於處理生產消費的問題
 * 
 * 實現機制:put/take利用重入鎖ReentrantLock實現同步效果
 */
public class ArrayBlockingQueueTest {

	public static void main(String[] args) {
		
        ArrayBlockingQueue<String> abq = new ArrayBlockingQueue<String>(3);

        new Thread(new Runnable() {
	
			@Override
			public void run() {
				while(true){
					try {
						Thread.sleep(1000);
						abq.put("Hello Java World");
						System.out.println(Thread.currentThread().getName()+":放入資料,剩餘資料:"+abq.size());
					} catch (Exception e) {
						e.printStackTrace();
					}	
				}
			}
		}).start();
        
        new Thread(new Runnable() {
			@Override
			public void run() {
				while(true){
					try {
						Thread.sleep(10000);
						abq.take();
						System.out.println(Thread.currentThread().getName()+":取出資料,剩餘資料:"+abq.size());
					} catch (Exception e) {
						e.printStackTrace();
					}	
				}
			}
		}).start();
	}
}

效果:

相關推薦

執行- JUC 4執行同步工具

浪費了“黃金五年”的Java程式設計師,還有救嗎? >>>   

執行- 4執行通訊方式

浪費了“黃金五年”的Java程式設計師,還有救嗎? >>>   

執行ListenableFuture非同步多執行查詢實現

  業務場景:為優化查詢效率,將原有查詢的條件做成單獨的索引表,每次產生記錄就會同步到索引表中,每次查詢索引表,根據索引便利的條件欄位再分別查詢每張子表的內容,最後封裝成前臺要的實體類。這裡面涉及到非同步查詢,如何保證一條記錄下的子表全部都查出來後才執行下面的操作。 下面Demo簡

學習筆記Java-Concurrent-多執行容器

BlockingQueue 阻塞佇列 高頻函式:   boolean put() 新增一個元素 沒有空間則一直阻塞等待   boolean add() 新增一個元素 沒有空間則丟擲IllegalStateException異常   boolean off

學習筆記Java-Concurrent-多執行測試模板

import java.util.concurrent.CountDownLatch; /** * 多執行緒測試模板 * * @author Mairuis * @date 2018/10/11 */ public class ConcurrentTest { public s

Java併發程式設計:4執行池和緩衝佇列BlockingQueue

一. 執行緒池簡介 1. 執行緒池的概念:           執行緒池就是首先建立一些執行緒,它們的集合稱為執行緒池。使用執行緒池可以很好地提高效能,執行緒池在系統啟動時即建立大量空閒的執行緒,程式將一個任務傳給執行緒池,執行緒池就會啟動一

執行開啟的4方法

//Task t = new Task();//(方法一) //Thread t = new Thread();//(方法二) //TaskFactory tf = new TaskFactory();//(方法三) //通過委託 開啟一個執行緒 //(方法四) //VS新建控制檯指令碼 .

Java併發Java中的執行

Java中的執行緒池 執行流程 執行緒池的建立 提交任務 關閉執行緒池 參考 執行流程 處理流程如下: execute()方法執行示意圖如下: 執行緒池的建立 corePoolSize:執行緒池

伺服器效能第二篇 分析執行日誌

1,執行緒狀態為“waiting for monitor entry”: 意味著它 在等待進入一個臨界區 ,所以它在”Entry Set“佇列中等待。 此時執行緒狀態一般都是 Blocked: java.lang.Thread.State: BLOCKED (on ob

技能庫--批量任務多執行併發執行(324)

擴充套件callable 介面 並且  Futrue<?>  import com.alibaba.fastjson.JSON; import com.google.common.collect.Lists; import com.google.commo

Qt開發事件迴圈與執行

初次讀到這篇文章,譯者感覺如沐春風,深刻體會到原文作者是花了很大功夫來寫這篇文章的,文章深入淺出,相信仔細讀完原文或下面譯文的讀者一定會有收穫。 由於原文很長,原文作者的行文思路是從事件迴圈逐漸延伸到執行緒使用的討論,譯者因時間受限,暫發表有關事件迴圈的譯文。另一半執行緒實用的譯文將近期公佈。文中有翻譯不當

Java多執行執行池(4)--執行池的五狀態

執行緒池的5種狀態:Running、ShutDown、Stop、Tidying、Terminated。 執行緒池各個狀態切換框架圖: 1、RUNNING (1) 狀態說明:執行緒池處在RUNNING狀態時,能夠接收新任務,以及對已新增的任務進行處理。

java基礎java語言的執行安全級別

java是支援多執行緒程式設計的語言,java中提供了很多類,如果把這些類的實現按照執行緒安全級別來排序的話,則由強到弱主要可以分為以下幾個級別 1 絕對執行緒安全 在任何環境下,呼叫者都不需要考慮額外的同步措施,都能夠保證程式的正確性。 這個定義要求很嚴格,java裡

java併發造成HashMap非執行安全的原因

0. 寫在前面   在前面我的一篇總結執行緒範圍內共享資料文章中提到,為了資料能線上程範圍內使用,我用了HashMap來儲存不同執行緒中的資料,key為當前執行緒,value為當前執行緒中的資料。

Executors建立的4執行池的使用

Java通過Executors提供四種執行緒池,分別為: newCachedThreadPool建立一個可快取執行緒池,如果執行緒池長度超過處理需要,可靈活回收空閒執行緒,若無可回收,則新建執行緒。 newFixedThreadPool 建立一個定長執行緒池,可控制執行緒最大

Swoole基礎Linux的多執行切換和多程序的切換

將大象裝冰箱,總共分三步,一把冰箱門開啟,二把大象轉進去,三把冰箱門關上,簡單粗暴。可惜我們的程序和執行緒的轉換不是大象裝冰箱問題,不扯淡了,迴歸正題。 一般的程序切換分為兩步 首先 切換頁目錄使用新的地址空間 然後 切換核心棧和硬體上下文 對於我們

4執行池的特點介紹

一、執行緒池的分類 FixThreadPool CachedThreadPool ScheduledThreadPool SingleThreadPool 二、特點介紹 1.FixedThreadPool 1.1 通過Exector的newF

執行——Runnable如何獲取執行執行結果?

     由於Runnable裡的多執行緒是沒有返回結果的,那麼現在我想讓Runnable定義的多執行緒有返回結果和能夠拋 出異常該怎麼處理呢? 方案:     在java中提供了一個多執行緒

java 總結4執行中操作UI介面的方法

private class LoadTask extends AsyncTask { protected String doInBackground( String... url ) { return loadDataFormNetwork(

為什麼要使用執行池;常見的建立執行池的4方式

1. 為什麼使用執行緒池諸如 Web 伺服器、資料庫伺服器、檔案伺服器或郵件伺服器之類的許多伺服器應用程式都面向處理來自某些遠端來源的大量短小的任務。請求以某種方式到達伺服器,這種方式可能是通過網路協議(例如 HTTP、FTP 或 POP)、通過 JMS 佇列或者可能通過輪詢