1. 程式人生 > >java.util.concurrent 併發工具包(二)

java.util.concurrent 併發工具包(二)

一、ThreadPoolExecutor 執行緒池執行者

  • 初始化執行緒池的引數
corePoolSize 核心執行緒大小
maximumPoolSize 最大執行緒大小
keepAliveTime 空餘的多餘執行緒保持時間
unit 時間單位
workQueue 阻塞佇列
handler 拒絕服務助手
  • 執行緒池內部執行機制

1、當有任務委託給執行緒池,若池中執行緒數量 < 核心執行緒數量,則建立新的執行緒,即使有空閒執行緒。

2、若核心執行緒數量已滿,且沒有空閒,則把任務放入阻塞佇列

3、若核心執行緒阻塞佇列都沒有空閒,此時再來任務,則判斷當前池內執行緒數量是否 < 最大執行緒數量

。若小於則建立臨時執行緒去處理該任務。

4、若核心執行緒阻塞佇列臨時執行緒都已經到達上限,且被佔用。此時再來任務,則由拒絕助手去處理。

  • 程式碼示例
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPoolExecutorDemo {

	public static void main(String[] args) throws InterruptedException {
		
		//阻塞佇列
		ArrayBlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<Runnable>(2);
		//拒絕助手
		RejectedExecutionHandler handler = new RejectedExecutionHandler() {
			@Override
			public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
				System.out.println("執行緒池已滿  ##### 任務被拒絕 ");
			}
		};
		//建立執行緒池
		ThreadPoolExecutor  pool =  new ThreadPoolExecutor(2, 4, 60L, TimeUnit.SECONDS, workQueue, handler);
										
		//1,2被核心執行緒處理
		pool.execute(new RunnableDemo(1,5000L));
		pool.execute(new RunnableDemo(2,5000L));
		Thread.sleep(100);
		//3,4放入阻塞佇列,等核心執行緒或臨時執行緒有空閒了再處理
		pool.execute(new RunnableDemo(3,2000L));
		pool.execute(new RunnableDemo(4,2000L));
		Thread.sleep(100);
		//5,6被臨時執行緒處理
		pool.execute(new RunnableDemo(5,2000L));
		pool.execute(new RunnableDemo(6,2000L));
		Thread.sleep(100);
		//7,8被拒接助手處理了
		pool.execute(new RunnableDemo(7,2000L));
		pool.execute(new RunnableDemo(8,2000L));
		
		//執行緒池關閉
		pool.shutdown();
		
	}

}

class RunnableDemo implements Runnable {
	
	private int id;
	private long time;
	
	public RunnableDemo(int id, long time) {
		this.id = id;
		this.time = time;
	}
	
	@Override
	public void run() {
		try {
			
			System.out.println("id=" + id + " 開始執行!時間:" + System.currentTimeMillis());
			Thread.sleep(time);
			System.out.println("id=" + id + " 執行完成!時間:" + System.currentTimeMillis());
			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
	}
	
}

二、ExecutorService 執行器服務

  • 獲取執行緒池

通過Executors類的各個靜態方法,可以直接獲取常用配置的執行緒池。

例如:

ExecutorService executorService = Executors.newFixedThreadPool(5);

其實內部也是用ThreadPoolExecutor來實現:

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
  • 執行
execute(Runnable) 沒有返回結果
submit(Runnable) 返回值型別為 Future,可以通過Future的get()方法來觀察任務是否執行結束。若沒結束,則該方法會阻塞。
submit(Callable)

與submit(Runnable)類似,唯一區別是submit(Callable)

還可以通過get() 方法獲取返回結果。

invokeAny() 入參為一個Callable或其子介面例項物件的集合,如果其中一個任務執行完成或者異常,其他的Callable將被取消。並返回其中一個Callable的執行結果。
invokeAll() 入參為一個Callable或其子介面例項物件的集合,執行所有任務,並返回一個Future物件的集合。但是無法通過Future知道任務是正常結束還是執行異常。
  • 關閉執行緒池
shutdown() 執行後則不再接受任務,直到任務執行完成才關閉
shutdownNow() 立即關閉
  • 程式碼示例
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class ExecutorServiceDemo {
	
	public static void main(String[] args) throws Exception {
		ExecutorService executorService = Executors.newFixedThreadPool(5);
		Future<String> future = executorService.submit(new CallableDemo());
		
		//阻塞直到任務結束
		System.out.println(future.get());
		
		executorService.shutdown();
		
	}
}

class CallableDemo implements Callable<String> {

	public String call() throws Exception {
		System.out.println("開始執行!");
		Thread.sleep(3000);
		System.out.println("執行結束!");
		
		return "[email protected]!";
	}
	
}

三、Lock鎖

作用類似synchronized,但是更靈活,通過lock(),unlock()兩個方法配合使用,保證執行緒安全。

lock() 將 Lock 例項鎖定
lockInterruptibly() lockInterruptibly() 方法將會被呼叫執行緒鎖定,除非該執行緒被打斷。此外,如果一個執行緒在通過這個方法來鎖定 Lock 物件時進入阻塞等待,而它被打斷了的話,該執行緒將會退出這個方法呼叫。
tryLock() 試圖立即鎖定 Lock 例項。並返回成功結果,永不阻塞
unlock 對 Lock 例項解鎖
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockDemo {
	public static void main(String[] args) throws InterruptedException {
		Lock lock = new ReentrantLock();
		
		Thread t1 = new Thread(new T1(lock));
		Thread t3 = new Thread(new T1(lock));
			t1.start();
			Thread.sleep(100);
			t3.start();
			t3.interrupt();
		
	}
}

class T1 implements Runnable {
	
	Lock lock = null;
	
	public T1(Lock lock) {
		this.lock = lock;
	}
	public void run() {
		
		try {
			//噹噹前執行執行緒被打斷時,當前執行緒會退出這個方法呼叫
			lock.lockInterruptibly();
			System.out.println("任務開始執行!");
			Thread.sleep(2000);
			System.out.println("任務執行結束!");
			
		} catch (Exception e) {
			System.out.println("執行緒被打斷");
		}finally {
			lock.unlock();
		}
		
	}
	
}

四、ReadWriteLock讀寫鎖

讀是可以併發處理的,但是讀和寫,或者多個寫是不可以併發處理的。

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockDemo {
	
	public static String name = "lisi";
	public static void main(String[] args) {
		ReadWriteLock lock = new ReentrantReadWriteLock();
		//read可以併發
		new Thread(new TRead(lock)).start();
		new Thread(new TRead(lock)).start();
		new Thread(new TRead(lock)).start();
		//read+write 或者 多個write不能併發
		new Thread(new TWrite(lock)).start();
		new Thread(new TWrite(lock)).start();
		new Thread(new TRead(lock)).start();
		
	}
}

class TWrite implements Runnable {
	private ReadWriteLock lock = null;
	
	public TWrite(ReadWriteLock lock) {
		this.lock = lock;
	}
	
	public void run() {
		
		try {
			lock.writeLock().lock();
			System.out.println(Thread.currentThread().getId() + "  # 開始寫資料");
			Thread.sleep(2000);
			ReadWriteLockDemo.name ="wangwu";
			System.out.println(Thread.currentThread().getId() + "  # 資料寫入成功" + ReadWriteLockDemo.name);
			lock.writeLock().unlock();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
	}
}

class TRead implements Runnable {
	private ReadWriteLock lock = null;
	
	public TRead(ReadWriteLock lock) {
		this.lock = lock;
	}
	
	public void run() {
		
		try {
			lock.readLock().lock();
			System.out.println(Thread.currentThread().getId() + "  # 開始讀資料");
			Thread.sleep(2000);
			ReadWriteLockDemo.name ="wangwu";
			System.out.println(Thread.currentThread().getId() + "  # 讀取到資料" + ReadWriteLockDemo.name);
			lock.readLock().unlock();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
	}
}

相關推薦

java.util.concurrent 併發工具()

一、ThreadPoolExecutor 執行緒池執行者 初始化執行緒池的引數 corePoolSize 核心執行緒大小 maximumPoolSize 最大執行緒大小 keepAliveTime 空餘的多餘執行緒保持時間 unit 時間

Java7 java.util.concurrent 併發計劃

原文連結,譯文連結,譯者:DOM,校對:鄭旭東  Java7釋出版本的具體計劃應該開始了,之前經常有人問我們關於JSR166的後續計劃包含哪些內容。下面是目前暫定的內容,歡迎提出你們的見 解和意見。 1.Phasers    一個通用的記憶體屏障實現。 2.LinkedTransferQue

Java併發:多執行緒和java.util.concurrent併發總結

引言前面已經針對Java多執行緒框架中具體的點介紹了很多了,現在是需要一個概括性總結的時候了,正好從網上找到一張描述java.util.concurrent包組成結構的類圖,正好可以對java多執行緒中

java.util.concurrent.atomic 類詳解

java.util.concurrent包分成了三個部分,分別是java.util.concurrent、java.util.concurrent.atomic和java.util.concurrent.lock。內容涵蓋了併發集合類、執行緒池機制、同步互斥機制、執行緒安全

java.util.concurrent java併發中部分工具的使用

java.util.concurrent.Semaphore(訊號量) https://www.cnblogs.com/nullzx/p/5270233.html https://my.oschina.net/cloudcoder/blog/362974  

Java 併發工具 java.util.concurrent 使用者指南

譯序 1. java.util.concurrent - Java 併發工具包 Java 5 添加了一個新的包到 Java 平臺,java.util.concurrent 包。這個包包含有一系列能夠讓 Java 的併發程式設計變得更加簡單輕鬆的類。在這個包被新

Java多執行緒()Java併發工具concurrent例項簡述

傳統的多執行緒並沒有提供高階特性,例如:訊號量、執行緒池和執行管理器等,而這些特性恰恰有助於建立強大的併發程式。新的Fork/Join框架針對當前的多核系統,也提供了並行程式設計的可能。這塊的內容是java多執行緒資訊量最大的一部分內容,本篇部落格循序漸進的,首

Java 併發工具-java.util.concurrent-原始碼jdk1.7全面解析

先來看看類圖: 其實從類圖我們能發現concurrent包(除去java.util.concurrent.atomic 和 java.util.concurrent.locks)中的內容並沒有特別多,大概分為四類:BlockingQueue阻塞佇列體系、Executor

Java併發程式設計-併發工具java.util.concurrent使用指南

譯序 1. java.util.concurrent - Java併發工具包 Java 5 添加了一個新的包到 Java 平臺,java.util.concurrent 包。這個包包含有一系列能夠讓 Java 的併發程式設計變得更加簡單輕鬆的類。在這

Java併發工具java.util.concurrent使用者指南

拋異常 特定值 阻塞 超時 插入 add(o) offer(o) put(o) offer(o, timeout, timeunit) 移除 remove(o) poll(o) take(o) poll(timeout, timeuni

Java學習筆記—多線程(並發工具類,java.util.concurrent.atomic

配對 初始 訪問 接收 iter nco .get 執行 string 在JDK的並發包裏提供了幾個非常有用的並發工具類。CountDownLatch、CyclicBarrier和Semaphore工具類提供了一種並發流程控制的手段,Exchanger工具類則提供了在線程間

為什麼java.util.concurrent 裡沒有併發的ArrayList實現?

原文連結 作者:Stephen C 譯者:鄭旭東  校對:方騰飛 問:JDK 5在java.util.concurrent裡引入了ConcurrentHashMap,在需要支援高併發的場景,我們可以使用它代替HashMap。但是為什麼沒有ArrayList的併發實現呢?難道在多執行緒場景下我們

java.util.concurrent下同步輔助工具類CountDownLatch

        CountDownLatch作為一個輔助工具類,它允許一個或多個執行緒等待一系列指定操作的完成。CountDownLatch以一個給定值進行初始化,通過CountDownLatch cd

執行緒併發執行緒安全介紹及java.util.concurrent下類介紹

執行緒Thread,在Java開發中多執行緒是必不可少的,但是真正能用好的並不多! 首先開啟一個執行緒三種方式  ①new Thread(Runnable).start()  ②thread.star

聊聊高併發十四)解析java.util.concurrent各個元件(六) 深入理解AQS(四)

最近整體過了下AQS的結構,也在網上看了一些講AQS的文章,大部分的文章都是泛泛而談。重新看了下AQS的程式碼,把一些新的要點拿出來說一說。 AQS是一個管程,提供了一個基本的同步器的能力,包含了一個狀態,修改狀態的原子操作,以及同步執行緒的一系列操作。它是CLHLock

聊聊高併發(三十)解析java.util.concurrent各個元件(十) 理解CyclicBarrier柵欄

這篇講講CyclicBarrier柵欄,從它的名字可以看出,它是可迴圈使用的。它的功能和CountDownLatch類似,也是讓一組執行緒等待,然後一起開始往下執行。但是兩者還是有幾個區別 1. 等待的物件不同。CountDownLatch的一組執行緒等待的是一個事件,或者

【一】關於java.util.concurrent下的併發類(atomic)

併發類包除了java.util.concurrent之外,還有java.util.concurrent.atomic和java.util.concurrent.lock.java.util.concurrent中主要是一些關於集合框架的併發實現,例如ConcurrentHas

知識梳理之Java併發相關(java.util.concurrent/Blocking/Concurrent/ThreadPoolExecutors/CopyOnWrite)

Java併發包提供了哪些併發工具類? 我們通常所說的併發包也就是 java.util.concurrent 及其子包,集中了 Java 併發的各種基礎工具類,具體主要包括幾個方面: 提供了比 synchronized 更加高階的各種同步結構,包括 Coun

聊聊高併發(四十)解析java.util.concurrent各個元件(十八) 任務的批量執行和CompletionService

上一篇講了ExecutorService關於任務的非同步執行和狀態控制的部分,這篇說說關於任務批量執行的部分。ExecutorSerivce中關於批量執行的介面如下 <T> List<Future<T>> invokeAll(Collec

Java多執行緒與高併發:java.util.concurrent

面試官:你用過JUC的哪些工具類? 前面從基礎開始,到執行緒安全的實現、物件的釋出與共享,涉及到很多執行緒安全的類與工具,JDK1