1. 程式人生 > 實用技巧 >Java併發程式設計之閉鎖與柵欄

Java併發程式設計之閉鎖與柵欄

一、前言

閉鎖與柵欄是在多執行緒程式設計中的概念,因為在多執行緒中,我們不能控制執行緒的執行狀態,所以給執行緒加鎖,讓其按照我們的想法有秩序的執行。

  • 閉鎖

CountDownLatch,例項化時需要傳入一個int型別的數字(count),意為等待count個執行緒完成之後才能執行下一步動作。

如今天要做的事情是吃晚飯,再去散步。假設11個人相約晚飯後一起去散步,我們得等11個人全都吃完晚飯了才能出發去散步。簡而言之就是做了才到達某一種狀態。

  • 柵欄

CyclicBarrier,例項化時需要傳入一個int型別的數字(parties),意為等待parties個執行緒都準備就緒後才能執行自己的任務。

如今天要做的事情是吃晚飯,8個人約好一起去某餐廳吃飯,得等到人齊了才能去吃飯。簡而言之就是到達某種狀態後一起做。

二、例項

閉鎖 CountDownLatch

package com.test;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;

public class Test {
	public static void main(String[] args) {
		CountDownLatch latch = new CountDownLatch(3);

                // 模擬三個任務
		List<String> jobs = new ArrayList<String>();
		jobs.add("first");
		jobs.add("second");
		jobs.add("third");

                // 迴圈執行任務
		for (String job : jobs) {
			new Thread(new Runnable() {

				@Override
				public void run() {
					System.out.println(Thread.currentThread().getName() + " : 進入run方法");
					latch.countDown();
					System.out.println(Thread.currentThread().getName() + " : 執行" + job);
				}
			}).start();
		}

		try {
			latch.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		// 任務都執行完後才執行
		System.out.println("回到main執行緒");
	}

}

執行結果:

Thread-1 : 進入run方法

Thread-2 : 進入run方法

Thread-2 : 執行third

Thread-0 : 進入run方法

Thread-1 : 執行second

Thread-0 : 執行first

回到main執行緒

通過執行結果可看出,當所有執行緒都執行完後才能回到主執行緒繼續執行後面的輸出。

柵欄 CyclicBarrier

package com.test;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class Test {
	public static void main(String[] args) {
		CyclicBarrier barrier = new CyclicBarrier(3);
		// 模擬建立三個任務
		List<String> jobs = new ArrayList<String>();
		jobs.add("first");
		jobs.add("second");
		jobs.add("third");
		//迴圈執行任務
		for (String job : jobs) {
			new Thread(new Runnable() {

				@Override
				public void run() {
					System.out.println(Thread.currentThread().getName() + " : 進入run方法");
					try {
						// 等待
						barrier.await();
					} catch (InterruptedException | BrokenBarrierException e) {
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + " : 執行" + job);
				}
			}).start();
		}
	}

}

執行結果:

Thread-1 : 進入run方法

Thread-2 : 進入run方法

Thread-0 : 進入run方法

Thread-0 : 執行first

Thread-1 : 執行second

Thread-2 : 執行third

通過執行結果可看出,當所有執行緒都執行都進入到run方法後,才能繼續執行自己內部的方法。