016.多執行緒-執行緒池的四種建立方式
前言
為什麼要用執行緒池
經常建立、銷燬 執行緒,將是對系統資源的極大浪費。
因此,實際開發中我們將使用執行緒池來管理、複用 執行緒。
使用執行緒池,可以
1.降低資源消耗: 重複利用執行緒,減少建立和銷燬造成的消耗。
2.提升響應速度: 任務到達,不需要建立,立即執行。
3.提高可管理型: 執行緒是CPU排程和分派的基本單位,
如果無限制地建立,不僅會消耗系統資源,還會降低系統穩定性。
使用執行緒池可以統一進行 分配、調優和監控。
執行緒池的分類
ThreadPoolExecutor
ThreadPoolExecutor是執行緒池的真正實現,
他通過構造方法的一系列引數,來構成不同配置的執行緒池。
常用的構造方法有下面四個
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler);
- corePoolSize: 核心池的大小。 當有任務來之後,就會建立一個執行緒去執行任務,當執行緒池中的執行緒數目達到corePoolSize後,就會把到達的任務放到快取隊列當中
- maximumPoolSize: 執行緒池最大執行緒數,它表示線上程池中最多能建立多少個執行緒;
- keepAliveTime: 表示執行緒沒有任務執行時最多保持多久時間會終止。
- unit: 引數keepAliveTime的時間單位,有7種取值,在TimeUnit類中有7種靜態屬性。
- workQueue:一個阻塞佇列,提交的任務將會被放到這個佇列裡。
- threadFactory:執行緒工廠,用來建立執行緒,主要是為了給執行緒起名字,預設工廠的執行緒名字:pool-1-thread-3。
- handler:拒絕策略,當執行緒池裡執行緒被耗盡,且佇列也滿了的時候會呼叫。
執行緒池的四種建立方式
Java通過Executors(jdk1.5併發包)提供四種執行緒池,分別為:
-
newCachedThreadPool建立一個可快取執行緒池,如果執行緒池長度超過處理需要,可靈活回收空閒執行緒,若無可回收,則新建執行緒。
案例演示: -
newFixedThreadPool 建立一個定長執行緒池,可控制執行緒最大併發數,超出的執行緒會在佇列中等待。
-
newScheduledThreadPool 建立一個定長執行緒池,支援定時及週期性任務執行。
-
newSingleThreadExecutor 建立一個單執行緒化的執行緒池,它只會用唯一的工作執行緒來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先順序)執行。
newCachedThreadPool
建立一個可快取執行緒池,如果執行緒池長度超過處理需要,可靈活回收空閒執行緒,
若無可回收,則新建執行緒。
package cn.qbz.thread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test111907 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int temp = i;
executorService.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " i=" + temp);
}
});
}
}
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
newFixedThreadPool
建立一個定長執行緒池,可控制執行緒最大併發數,超出的執行緒會在佇列中等待。
package cn.qbz.thread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test111907 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
final int temp = i;
executorService.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " i=" + temp);
}
});
}
}
}
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
newScheduledThreadPool
建立一個定長執行緒池,支援定時及週期性任務執行。
package cn.qbz.thread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Test111907 {
public static void main(String[] args) {
final long begin = System.currentTimeMillis();
ExecutorService executorService = Executors.newScheduledThreadPool(3);
for (int i = 0; i < 10; i++) {
final int temp = i;
final long time = begin;
executorService.schedule(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " i=" + temp + " time=" + (System.currentTimeMillis() - time));
}
}, 5, TimeUnit.SECONDS);
}
}
}
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
new DelayedWorkQueue());
}
newSingleThreadExecutor
建立一個單執行緒化的執行緒池,它只會用唯一的工作執行緒來執行任務,
保證所有任務按照指定順序(FIFO, LIFO, 優先順序)執行。
package cn.qbz.thread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Test111907 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int temp = i;
executorService.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " i=" + temp);
}
});
}
}
}