顾名思义,线程池就是存放线程的池子。直接用线程不就好了吗,为什么还需要线程池呢?

相比进程,线程已经轻量很多了,创建和销毁线程消耗的资源会少很多,但终究还是有消耗的。为了进一步降低消耗,我们需要用到线程池。需要用到线程时不用申请,直接从线程池中取,用完之后也不用销毁,再放进线程池。

标准库中的线程池(简化版本):

1
2
3
4
5
6
7
8
9
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(10);
pool.submit(new Runnable() {
@Override
public void run() {
System.out.println("hello");
}
});
}

模拟实现一个简化版本的线程池:

  1. 描述任务:直接用Runnable接口即可
  2. 组织任务:用到阻塞队列
  3. 描述工作线程:创建Worker类继承Thread,重写run方法,从阻塞队列中取任务,然后执行任务
  4. 组织工作线程:实例化工作线程,加入到线程池,启动线程
  5. 提交任务:往线程池中添加任务(具体是将任务添加到阻塞队列)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
public class ThreatPool {
//描述一个任务
//组织一个任务
BlockingDeque<Runnable> queue = new LinkedBlockingDeque<>();
//描述一个线程
//线程是用来执行任务的,而任务都存放在队列中
static class Worker extends Thread{
//通过构造方法能够拿到外面的queue
private BlockingDeque<Runnable> queue = null;
public Worker(BlockingDeque<Runnable> queue) {
this.queue = queue;
}

@Override
public void run() {
//从queue中取任务,然后执行任务
while(true){
try {
Runnable runnable = queue.take();
runnable.run();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//组织线程,创建线程
List<Worker> workers = new LinkedList<>();
public ThreatPool(int n) {
for (int i = 0; i < n; i++) {
//创建线程,存放到线程池,执行线程
Worker worker = new Worker(queue);
workers.add(worker);
worker.start();
}
}
//提交任务到线程
public void sumbit(Runnable runnable) throws InterruptedException {
queue.put(runnable);
}

public static void main(String[] args) throws InterruptedException {
ThreatPool pool = new ThreatPool(10);//线程数10
//执行1000个任务
for (int i = 0; i < 1000; i++) {
int workId = i;
pool.sumbit(new Runnable() {
@Override
public void run() {
System.out.println("任务:"+workId+Thread.currentThread().getName());
}
});
}
}
}