boost创建线程池_Java并发 之 线程池系列 (1) 让多线程不再坑爹的线程池
目錄
- 背景
- 線程池的來由
- 什么是線程池
- 背景總結
- 用法
- 通過Executors創建線程池
- Executors及其服務的類
- Executors常用的幾個方法
- 一個線程池的例子
- 任務
- 池子
- 測試
- 說明
- 通過Executors創建線程池
- 總結
- Links
- 文章友鏈
- 相關資源
背景
線程池的來由
服務端的程序,例如數據庫服務器和Web服務器,每次收到客戶端的請求,都會創建一個線程來處理這些請求。
創建線程的方式又很多,例如繼承Thread類、實現Runnable或者Callable接口等。
通過創建新的線程來處理客戶端的請求,這種看起來很容易的方法,其實是有很大弊端且有很高的風險的。
俗話說,簡單的路越走越困難,困難的路越走越簡單,就是這個道理。
創建和銷毀線程,會消耗大量的服務器資源,甚至創建和銷毀線程消耗的時間比線程本身處理任務的時間還要長。
由于啟動線程需要消耗大量的服務器資源,如果創建過多的線程會造成系統內存不足(run out of memory),因此限制線程創建的數量十分必要。
什么是線程池
線程池通俗來講就是一個取出和放回提前創建好的線程的池子,概念上,類似數據庫的連接池。
那么線程池是如何發揮作用的呢?
實際上,線程池是通過重用之前創建好線程來處理當前任務,來達到大大降低線程頻繁創建和銷毀導致的資源消耗的目的。
A thread pool reuses previously created threads to execute current tasks and offers a solution to the problem of thread cycle overhead and resource thrashing. Since the thread is already existing when the request arrives, the delay introduced by thread creation is eliminated, making the application more responsive.背景總結
下面總結一下開篇對于線程池的一些介紹。
但到底怎么使用線程池呢?線程池真的這么簡單好用嗎?線程池使用的過程中有沒有什么坑?
不要著急,下面就結合具體的示例,跟你講解各種使用線程池的姿勢,以及這些姿勢爽在哪里,痛在哪里。
準備好紙巾,咳咳...,是筆記本,濤哥要跟你開講啦!
用法
通過Executors創建線程池
Executors及其服務的類
java.util.concurrent.Executors是JDK的并發包下提供的一個工廠類(Factory)和工具類(Utility)。
Executors提供了關于Executor, ExecutorService, ScheduledExecutorService, ThreadFactory 和 Callable相關的工廠方法和工具方法。
Executor是一個執行提交的Runnable Tasks的對象,它有一個execute方法,參數是Runnable。當執行execute方法以后,會在未來某個時間,通過創建線程或者使用線程池中的線程的方式執行參數中的任務。用法如下:
Executor executor = anExecutor; executor.execute(new RunnableTask1()); executor.execute(new RunnableTask2());ExecutorService繼承了Executor,并提供了更多有意思的方法,比如shutdown方法會讓ExecutorService拒絕創建新的線程來執行task。
Executors常用的幾個方法
//創建固定線程數量的線程池 ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);//創建一個線程池,該線程池會根據需要創建新的線程,但如果之前創建的線程可以使用,會重用之前創建的線程 ExecutorService cachedThreadPool = Executors.newCachedThreadPool();//創建一個只有一個線程的線程池 ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();一個線程池的例子
下面我就創建5個Task,并通過一個包含3個線程的線程池來執行任務。我們一起看下會發生什么。
Github 完整代碼: 一個線程池的例子
?
ThreadPoolExample1就是我們的測試類,下面所有的內部類、常量和方法都寫在這個測試類里。
package net.ijiangtao.tech.concurrent.jsd.threadpool;import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;public class ThreadPoolExample1 {}任務
Task內部類執行了兩次for循環,并在每次循環執行結束以后 sleep 1秒鐘。
// Task class to be executed (Step 1) static class Task implements Runnable {private String name;public Task(String s) {name = s;}// Prints task name and sleeps for 1s// This Whole process is repeated 2 timespublic void run() {try {for (int i = 0; i <= 1; i++) {if (i == 0) {//prints the initialization time for every taskprintTimeMsg("Initialization");} else {// prints the execution time for every taskprintTimeMsg("Executing");}Thread.sleep(1000);}System.out.println(name + " complete");} catch (InterruptedException e) {e.printStackTrace();}}private void printTimeMsg(String state) {Date d = new Date();SimpleDateFormat ft = new SimpleDateFormat("hh:mm:ss");System.out.println(state+" Time for"+ " task name - " + name + " = " + ft.format(d));} }池子
創建一個固定線程數的線程池。
// Maximum number of threads in thread pool static final int MAX_T = 3; // creates a thread pool with MAX_T no. of // threads as the fixed pool size(Step 2) private static final ExecutorService pool = Executors.newFixedThreadPool(MAX_T);測試
創建5個任務,并通過線程池的線程執行這些任務。
public static void main(String[] args) {// creates five tasksRunnable r1 = new Task("task 1");Runnable r2 = new Task("task 2");Runnable r3 = new Task("task 3");Runnable r4 = new Task("task 4");Runnable r5 = new Task("task 5");// passes the Task objects to the pool to execute (Step 3)pool.execute(r1);pool.execute(r2);pool.execute(r3);pool.execute(r4);pool.execute(r5);// pool shutdown ( Step 4)pool.shutdown(); }執行結果如下。
Initialization Time for task name - task 1 = 12:39:44 Initialization Time for task name - task 2 = 12:39:44 Initialization Time for task name - task 3 = 12:39:44 Executing Time for task name - task 3 = 12:39:45 Executing Time for task name - task 1 = 12:39:45 Executing Time for task name - task 2 = 12:39:45 task 2 complete Initialization Time for task name - task 4 = 12:39:46 task 3 complete Initialization Time for task name - task 5 = 12:39:46 task 1 complete Executing Time for task name - task 5 = 12:39:47 Executing Time for task name - task 4 = 12:39:47 task 5 complete task 4 complete說明
從輸出的結果我們可以看到,5個任務在包含3個線程的線程池執行。
由于線程的執行有一定的隨機性,以及不同機器的資源情況不同,每次的執行結果,可能會有差異。
下面是我第二次執行的結果。
Initialization Time for task name - task 1 = 12:46:33 Initialization Time for task name - task 3 = 12:46:33 Initialization Time for task name - task 2 = 12:46:33 Executing Time for task name - task 2 = 12:46:34 Executing Time for task name - task 3 = 12:46:34 Executing Time for task name - task 1 = 12:46:34 task 3 complete task 2 complete task 1 complete Initialization Time for task name - task 4 = 12:46:35 Initialization Time for task name - task 5 = 12:46:35 Executing Time for task name - task 4 = 12:46:36 Executing Time for task name - task 5 = 12:46:36 task 5 complete task 4 completetask 1 2 3 獲得線程資源,task 4 5排隊等待:
task 1 2 3 執行結束,task 4 5獲得線程資源,線程池中有一個線程處于空閑狀態:
但規律是相同的,那就是線程池會將自己的線程資源貢獻出來,如果任務數超出了線程池的線程數,就會阻塞并排隊等待有可用的線程資源以后執行。
也就是線程池會保證你的task在將來(Future)的某個時間執行,但并不能保證什么時間會執行。
相信你現在對于ExecutorService的invokeAll方法,可以執行一批task并返回一個Future集合,就會有更深入的理解了。
List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException通過ExecutorService線程池執行task的過程如下圖所示,超出線程池線程數量的task將會在BlockingQueue排隊等待獲得線程資源的機會。
關于并發編程中的Futrue,筆者有一篇文章(Java并發編程-Future系列之Future的介紹和基本用法)專門介紹,請通過下面任意的鏈接移步欣賞:
- Future-掘金
- Future-簡書
總結
本教程帶領大家了解了線程池的來由、概念和基本用法,相信大家看完,以后就不再只會傻傻地new Thread了。
本節只是線程池的入門,下面會介紹關于線程池的更多武功秘籍,希望大家持續關注,有所獲益。
喜歡請點贊轉發,如果大家對這個系列感興趣,我會繼續更新的。
Links
文章友鏈
- Java并發 之 Future系列 (1) Future的介紹和基本用法
- Github-JavaStudyDemo-Concurrent
相關資源
Concurrent-ThreadPool-線程池拒絕策略RejectedExecutionHandler
Concurrent-ThreadPool-ThreadPoolExecutor里面4種拒絕策略
Concurrent-ThreadPool-線程池ThreadPoolExecutor構造方法和規則
Concurrent-ThreadPool-線程池的成長之路
Concurrent-ThreadPool-LinkedBlockingQueue和ArrayBlockingQueue的異同
Concurrent-ThreadPool-最佳線程數總結
Concurrent-ThreadPool-最佳線程數
Concurrent-ThreadPool-Thread Pools in Java
Concurrent-ThreadPool-java-thread-pool
Concurrent-ThreadPool-thread-pool-java-and-guava
Concurrent-ThreadPool-ijiangtao.net
總結
以上是生活随笔為你收集整理的boost创建线程池_Java并发 之 线程池系列 (1) 让多线程不再坑爹的线程池的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 姑娘对象是军官结婚政审但是我18就没在老
- 下一篇: r语言绘制精美pcoa图_R语言绘制交互