线程池是什么
线程池可以看成是一个公司的额定员工。当有任务时,如果当前员工数量没有达到额定员工数,公司就会另外雇一个实习生去完成任务;如果当前员工数达到额定员工数,公司就会在接下来的计划里面安排上这个任务,等公司里的员工空闲了再让他们做。
线程池的优点:可以减少每次启动,销毁线程的损耗
标准库里的线程池
这里我们需要
- 一个实现了ExecutorService接口的对象
- 对这个对象进行添加执行代码操作的方法
ExecutorService pool= Executors.newFixedThreadPool(10);
pool.submit(new Runnable(){
public void run(){
System.out.println("kunkun");
}
});
解析:
- ExecutorService 是一个接口,用来规范对线程池的使用。
- Executors 是一个实现了ExecutorService接口的类
- newFixedThreadPool() 是Executors类中用来实例化ExecutorService接口对象的方法(不用你自己实例化,舒服吧)
- 10 是实例化线程池中的线程容纳量
- submit() 是ExecutorService 接口的一部分,用来将Runnable或者Callable 对象(包含需要执行的代码)提交给线程池,如果有空闲的线程就执行,如果没有就放入等待队列中,等到线程空闲在执行。
创建线程池的几种方式
定-动-单-延
- 固定线程数线程池--------newFixedThreadPool()
- 动态线程数线程池--------newCachedThreadPool()
- 单线程的线程池--------newSingleThreadExecutor()
- 延时执行的线程池(进阶版Timer)--------newScheduledThreadPool()
Executor实际上是ThreadPoolExecutor的封装。
实现线程池
- submit线程池的核心,用于将任务(Runnable)存入线程池
- Runnable中的run方法写用来执行的代码,也就是任务
- BlockingQueue存放任务的阻塞队列
- worker是Worker的实例化对象,是新增方法的线程,用于从阻塞队列里取任务执行
class Worker extends Thread {
private LinkedBlockingQueue<Runnable> queue = null;
public Worker(LinkedBlockingQueue<Runnable> queue) {
super("worker");
this.queue = queue;
}
@Override
public void run() {
// try 必须放在 while 外头, 或者 while 里头应该影响不大
try {
while (!Thread.interrupted()) {
Runnable runnable = queue.take();
runnable.run();
}
} catch (InterruptedException e) {
}
}
}
public class MyThreadPool {
private int maxWorkerCount = 10;
private LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue();
public void submit(Runnable command) {
if (workerList.size() < maxWorkerCount) {
// 当前 worker 数不足, 就继续创建 worker
Worker worker = new Worker(queue);
worker.start();
}
// 将任务添加到任务队列中
queue.put(command);
}
public static void main(String[] args) throws InterruptedException {
MyThreadPool myThreadPool = new MyThreadPool();
myThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println("吃饭");
}
});
Thread.sleep(1000);
}
}