線程池工作流程:
核心線程數(corePoolSize) :核心線程數的設計需要依據任務的處理時間和每秒產生的任務數量來確定,例如:執行一個任務需要0.1秒,系統百分之80的時間每秒都會產生100個任務,那么要想在1秒內處理完這100個任務,就需要10個線程,此時我們就可以設計核心線程數為10;當然實際情況不可能這么平均,所以我們一般按照8020原則設計即可,既按照百分之80的情況設計核心線程數,剩下的百分之20可以利用最大線程數處理。
任務隊列長度(workQueue):任務隊列長度一般設計為:核心線程數/單個任務執行時間*2即可(2表示最大等待時間為2秒);例如上面的場景中,核心線程數設計為10,單個任務執行時間為0.1秒,則隊列長度可以設計為200。
最大線程數(maximumPoolSize):最大線程數的設計除了需要參照核心線程數的條件外,還需要參照系統每秒產生的最大任務數決定:例如:上述環境中,如果系統每秒最大產生的任務是1000個,那么,最大線程數=(最大任務數-任務隊列長度)*單個任務執行時間;既: 最大線程數=(1000-200)*0.1=80個。
最大空閑時間(keepAliveTime) 這個參數的設計完全參考系統運行環境和硬件壓力設定,沒有固定的參考值,用戶可以根據經驗和系統產生任務的時間間隔合理設置一個值即可;
上面4個參數的設置只是一般的設計原則,並不是固定的,可以根據實際情況靈活調整!
自定義線程池:
/* 需求: 自定義線程池練習,這是任務類,需要實現Runnable; 包含任務編號,每一個任務執行時間設計為0.2秒 */ public class MyTask implements Runnable{ private int id; //由於run方法是重寫接口中的方法,因此id這個屬性初始化可以利用構造方法完成 public MyTask(int id) { this.id = id; } @Override public void run() { String name = Thread.currentThread().getName(); System.out.println("線程:"+name+" 即將執行任務:"+id); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("線程:"+name+" 完成了任務:"+id); } @Override public String toString() { return "MyTask{" + "id=" + id + '}'; } }
/* 需求: 編寫一個線程類,需要繼承Thread類,設計一個屬性,用於保存線程的名字; 設計一個集合,用於保存所有的任務; */ public class MyWorker extends Thread{ private List<Runnable> tasks;
//利用構造方法,給成員變量賦值 public MyWorker(String name, List<Runnable> tasks) { super(name); this.tasks = tasks; } @Override public void run() { //判斷集合中是否有任務,只要有,就一直執行任務 while (tasks.size()>0){ Runnable r = tasks.remove(0); r.run(); } } }
/* 這是自定義的線程池類; 成員變量: 1:任務隊列 集合 需要控制線程安全問題 2:當前線程數量 3:核心線程數量 4:最大線程數量 5:任務隊列的長度 成員方法 1:提交任務; 將任務添加到集合中,需要判斷是否超出了任務總長度 2:執行任務; 判斷當前線程的數量,決定創建核心線程還是非核心線程 */ public class MyThreadPool { // 1:任務隊列 集合 需要控制線程安全問題 private List<Runnable> tasks = Collections.synchronizedList(new LinkedList<>()); //2:當前線程數量 private int num; //3:核心線程數量 private int corePoolSize; //4:最大線程數量 private int maxSize; //5:任務隊列的長度 private int workSize; public MyThreadPool(int corePoolSize, int maxSize, int workSize) { this.corePoolSize = corePoolSize; this.maxSize = maxSize; this.workSize = workSize; } //1:提交任務; public void submit(Runnable r){ //判斷當前集合中任務的數量,是否超出了最大任務數量 if(tasks.size() >= workSize){ System.out.println("任務:"+r+"被丟棄了..."); }else { tasks.add(r); //執行任務 execTask(r); } } //2:執行任務; private void execTask(Runnable r) { //判斷當前線程池中的線程總數量,是否超出了核心數, if(num < corePoolSize){ new MyWorker("核心線程:"+num,tasks).start(); num++; }else if(num < maxSize){ new MyWorker("非核心線程:"+num,tasks).start(); num++; }else { System.out.println("任務:"+r+" 被緩存了..."); } } }
/* 測試類: 1: 創建線程池類對象; 2: 提交多個任務 */ public class MyTest { public static void main(String[] args) { //1:創建線程池類對象; MyThreadPool pool = new MyThreadPool(2,4,20); //2: 提交多個任務 for (int i = 0; i <30 ; i++) { //3:創建任務對象,並提交給線程池 MyTask my = new MyTask(i); pool.submit(my); } } }
Java內置線程池:
package com.fgy.demo07; public class RunnableImpl implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName() + "創建了一個新的線程"); } }
package com.fgy.demo07; public class ExtendsThread extends Thread { @Override public void run() { System.out.println(Thread.currentThread().getName() + "創建了一個新的線程"); } }
package com.fgy.demo07; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Demo01ThreadTool { public static void main(String[] args) { ExecutorService pool = Executors.newFixedThreadPool(3); // 創建線程池,初始化有三個線程 pool.submit(new RunnableImpl()); pool.submit(new Runnable(){ @Override public void run() { System.out.println(Thread.currentThread().getName() + "創建了一個新的線程"); } }); pool.submit(new Thread(){ @Override public void run() { System.out.println(getName() + "創建了一個新的線程"); } }); pool.submit(new ExtendsThread()); // pool-1-thread-2創建了一個新的線程 // Thread-0創建了一個新的線程 // pool-1-thread-3創建了一個新的線程 // pool-1-thread-1創建了一個新的線程 // 銷毀線程池 pool.shutdown(); } }