提問(wèn)
線(xiàn)程的應(yīng)用場(chǎng)景都有什么?
如果并發(fā)數(shù)量非常多,但是每個(gè)線(xiàn)程執(zhí)行的時(shí)間都特別短族购,該如何設(shè)計(jì)?
線(xiàn)程池
A thread pool is a collection of pre-initialized threads.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.
參考:
Thread Pools in Java
Introduction to Thread Pools in Java
什么時(shí)候使用線(xiàn)程池财著?
- 單個(gè)任務(wù)處理時(shí)間比較短
- 需要處理的任務(wù)數(shù)量很大
使用線(xiàn)程池的好處
- 降低資源消耗
通過(guò)重復(fù)利用已創(chuàng)建的線(xiàn)程降低線(xiàn)程創(chuàng)建和銷(xiāo)毀造成的消耗 - 提高響應(yīng)速度
當(dāng)任務(wù)到達(dá)時(shí)联四,任務(wù)可以不需要的等到線(xiàn)程創(chuàng)建就能立即執(zhí)行 - 提高線(xiàn)程的可管理性
線(xiàn)程是稀缺資源撑碴,如果無(wú)限制的創(chuàng)建撑教,不僅會(huì)消耗系統(tǒng)資源,還會(huì)降低系統(tǒng)的穩(wěn)定性醉拓,使用線(xiàn)程池可以進(jìn)行統(tǒng)一的分配伟姐,調(diào)優(yōu)和監(jiān)控。
示例
public class WorkerThread implements Runnable {
private String command;
public WorkerThread(String s) {
this.command = s;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " Start. Command = " + command);
processCommand();
System.out.println(Thread.currentThread().getName() + " End.");
}
private void processCommand() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public String toString() {
return this.command;
}
}
執(zhí)行
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
Runnable worker = new WorkerThread("" + i);
executor.execute(worker);
}
executor.shutdown();
while (!executor.isTerminated()) {
}
System.out.println("Finished all threads");
查看結(jié)果亿卤,這是一個(gè)最簡(jiǎn)單的線(xiàn)程池的執(zhí)行方式愤兵。而且IDE有警告提示,這并不會(huì)有執(zhí)行問(wèn)題排吴。
拓展
另外輸出一個(gè)監(jiān)聽(tīng)線(xiàn)程秆乳,代碼如下:
public class MyMonitorThread implements Runnable {
private ThreadPoolExecutor executor;
private int seconds;
private boolean run = true;
public MyMonitorThread(ThreadPoolExecutor executor, int delay) {
this.executor = executor;
this.seconds = delay;
}
public void shutdown() {
this.run = false;
}
@Override
public void run() {
while (run) {
System.out.println(
String.format("[monitor] [%d/%d] Active: %d, Completed: %d, Task: %d, isShutdown: %s, isTerminated: %s",
this.executor.getPoolSize(),
this.executor.getCorePoolSize(),
this.executor.getActiveCount(),
this.executor.getCompletedTaskCount(),
this.executor.getTaskCount(),
this.executor.isShutdown(),
this.executor.isTerminated()));
try {
Thread.sleep(seconds * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
執(zhí)行方式:
public class WorkerPool {
public static void main(String args[]) throws InterruptedException {
RejectedExecutionHandlerImpl rejectionHandler = new RejectedExecutionHandlerImpl();
/** 用來(lái)創(chuàng)建新的線(xiàn)程 **/
ThreadFactory threadFactory = Executors.defaultThreadFactory();
/** 創(chuàng)建線(xiàn)程池 **/
ThreadPoolExecutor executorPool = new ThreadPoolExecutor(2, 4, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(2), threadFactory, rejectionHandler);
MyMonitorThread monitor = new MyMonitorThread(executorPool, 3);
Thread monitorThread = new Thread(monitor);
monitorThread.start();
for (int i = 0; i < 10; i++) {
executorPool.execute(new WorkerThread("cmd" + i));
}
Thread.sleep(30000);
executorPool.shutdown();
Thread.sleep(5000);
monitor.shutdown();
}
}
參考
ThreadPoolExecutor – Java Thread Pool Example
Introduction to Thread Pools in Java
Thread Pools in Java
深入理解 Java 線(xiàn)程池:ThreadPoolExecutor