通过util.concurrent.Executors直接创建线程池,非常方便
package thread.pool;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 使用线程池的好处:
* 线程池维护一定数量的worker线程
* 调用者只需将任务放入到线程池中即可
* 具体任务的执行交给线程池中的线程去完成
* 主要为了提高系统响应能力
* concurrent为并发提供支持,关注并发
* synchronized同步为共享资源安全使用提供支持,关注共享数据被正确操作
*/
class ThreadPool {
private static ThreadPool pool = new ThreadPool();
public static ThreadPool getThreadPool() {
return pool;
}
final int nThreads = 5;
ExecutorService executor = null;
//创建固定大小的线程池,线程池中的线程会不断被重用(当空闲时)
private ThreadPool() {
/**
* 始终维护固定数量的线程,线程在执行过程中由于错误导致终止,将会自动创建新的线程进行替补
*/
executor = Executors.newFixedThreadPool(nThreads);
/**
* 任务数超过线程池中处理任务的线程数量时,会自动创建新的线程并加入到线程池中执行任务
* 线程数量会根据任务多少动态变化(自动创建新线程或释放多余的空闲线程)
*/
//executor = Executors.newCachedThreadPool();
/**
* 线程池中只有唯一线程,即使发生错误导致线程终止(在shutdown()调用之前),线程池会自动创建一个新的线程进行替补
* 与newFixedThreadPool(1)不同的时,此方法返回的executor确保线程池不会被添加新的线程,始终只有一个,能实现任务执行的连续性/前后性
*/
//executor = Executors.newSingleThreadExecutor();
}
public ThreadPool addTask(Runnable task) {
executor.execute(task);
return this;
}
public void shutdown() {
executor.shutdown();
}
}
/**
* 封装任务
*/
class Task implements Runnable {
//统计每个线程总共执行了多少个任务
private static ThreadLocal<Integer> dealTaskCount = new ThreadLocal<Integer>();
private String taskName;
public Task(String taskName) {
this.taskName = taskName;
}
public void run() {
Integer taskCount = dealTaskCount.get();
taskCount = taskCount==null? 1 : ++taskCount;
dealTaskCount.set(taskCount);
System.out.println(Thread.currentThread().getName() + " dealing task: " + taskName +", complete task:" + taskCount);
try {
Thread.sleep(new Random().nextInt(100));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//Test
public class Concurrent_ThreadPool {
public static void main(String[] args) {
ThreadPool pool = ThreadPool.getThreadPool();
//提交50个任务到线程池中
for(int i=1;i<=50;i++) {
pool.addTask(new Task("Task"+i));
}
//when server shutdown
pool.shutdown();
}
}