简单模拟实现一个线程池
池(Pool)是一个非常重要的思想方法. 内存池, 进程池, 连接池, 常量池......
那么, 为什么从池子里取就比从系统这里创建线程更快更高效呢?
线程池最⼤的好处就是减少每次启动、销毁线程的损耗。
标准库中的线程池
• 使⽤ Executors.newFixedThreadPool(10) 能创建出固定包含 10 个线程的线程池.
• 返回值类型为 ExecutorService.
• 通过 ExecutorService.submit 可以注册⼀个任务到线程池中.
//线程池的使用
public class Demo23 {
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(5);
for (int i = 0; i < 1000; i++) {
service.submit(new Runnable() {
@Override
public void run() {
System.out.println("hello");
}
});
}
}
}
Executors 创建线程池的⼏种⽅式
• newFixedThreadPool: 创建固定线程数的线程池
• newCachedThreadPool: 创建线程数⽬动态增⻓的线程池.
• newSingleThreadExecutor: 创建只包含单个线程的线程池.
• newScheduledThreadPool: 设类似于定时器的效果.添加一些任务,任务都在后续的某个时刻再执行.被执行的时候不是只有一个扫描线程来执行任务, 可能是由多个线程共同执行所有的任务.
线程池对象搞好了之后, 使用submit方法, 就可以把任务添加到线程池中.
除了上述这些线程池之外,标准库还提供了一个接口更丰富的线程池类.
上面谈到的线程池,
—组线程池,是封装过的 Executors.
一组线程池,ThreadPoolExecutor原生的.
用哪个都可以,主要还是看实际的需求.
模拟实现一个线程池
class MyThreadPool {
private BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
// 通过这个方法, 将任务添加到线程池中
public void submit(Runnable runnable) throws InterruptedException {
queue.put(runnable);
}
// n 表示线程池里有几个线程
// 创建了一个固定数量的线程池
public MyThreadPool(int n) {
for (int i = 0; i < n; i++) {
Thread t1 = new Thread(() -> {
while (true) {
try {
// 取任务, 并执行任务
Runnable runnable = queue.take();
runnable.run();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
}
}
}
// 模拟实现一个线程池
public class Demo24 {
public static void main(String[] args) throws InterruptedException {
MyThreadPool pool = new MyThreadPool(4);
for (int i = 0; i < 1000; i++) {
pool.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " hello");
}
});
}
}
}