赞
踩
在执行并发任务时,往往是通过new Thread() 方法来创建一个新的线程,这样做的弊端会比较多,比如最大的弊端就是频繁创建和销毁线程资源的损耗。所以我们有了线程池,接下来将会好好介绍线程池
从名字来看,我们可以猜测这是一个用来装线程的池子。这时就会想到字符串常量池,字符串常量池是为了提高程序运行效率提出来的,那这个线程池也是为了提高效率吗?当我们知道一个线程的创建和销毁的过程,就会知道创建一个线程开销比创建一个进程消耗要小,但是频繁创建的开销也是不可以忽视的,所以我们有了线程池,提前创建好,放入到这个池子里,就不会出现频繁创建(进入 内核态)。最重要的是线程池也是会提高效率的,当我们调度线程的时候,从线程池拿取线程,是属于用户态操作,而重新去创建一个线程,会涉及到用户态和内核态之间的切换,当进入内核态,那么效率就会比较低了,因为当你把任务交给内核态,内核态不一定立马去完成,它可能晚点才完成,但是交给用户态,会立马去完成,当直接调用线程池存在的线程完成任务,会提高效率。
使用 Executors.newFixedThreadPool(n) 能创建出固定包含 n 个线程的线程池.
返回值类型为 ExecutorService
通过 ExecutorService.submit 可以注册一个任务到线程池中
代码如下:
ExecutorService pool = Executors.newFixedThreadPool(10);
pool.submit(new Runnable() {
@Override
public void run() {
System.out.println("hello");
}
});
Executors 本质上是 ThreadPoolExecutor 类的封装.
代码演示:
public class Demo16 {
public static void main(String[] args) {
//创建一个含有10个线程的线程池
ExecutorService pool = Executors.newFixedThreadPool(10);
//添加20个任务到线程池中
for (int i = 0; i < 20; i++) {
pool.submit(new Runnable() {
@Override
public void run() {
System.out.println("嗨,threadpool");
}
});
}
}
}
1.创建一个阻塞队列用来存放任务
private BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
2.描述一个工作线程,这个线程的工作是从任务队列拿到任务执行
static class Worker extends Thread{ BlockingQueue<Runnable> queue = null; //构造方法拿到外面的任务队列 public Worker(BlockingQueue queue) { this.queue = queue; } @Override public void run() { while (true) { try { Runnable runnable = queue.take(); //如果为空会进入阻塞 runnable.run(); } catch (InterruptedException e) { e.printStackTrace(); } } } }
3.创建一个链表结构存放线程
private List<Thread> workers = new ArrayList<>();
4.构造方法确定所添加的核心线程数并创建
public MyThreadPool(int n) {
for (int i = 0; i < n; i++) {
Worker worker = new Worker(queue); //这是准备好了
worker.start(); //只有进入了start线程才被创好
workers.add(worker); //添加到链表上
}
}
5.创建一个方法添加任务到队列中
public void submit(Runnable runnable){
try {
queue.put(runnable);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
这样一个线程池就完整的实现了
总代码如下:
class MyThreadPool { //创建一个阻塞队列用来存放任务 private BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(); //描述一个线程,这个线程的工作是从任务队列拿到任务执行 static class Worker extends Thread{ BlockingQueue<Runnable> queue = null; //构造方法拿到外面的任务队列 public Worker(BlockingQueue queue) { this.queue = queue; } @Override public void run() { while (true) { try { Runnable runnable = queue.take(); //如果为空会进入阻塞 runnable.run(); } catch (InterruptedException e) { e.printStackTrace(); } } } } //创建一个链表结构存放线程 private List<Thread> workers = new ArrayList<>(); //构造方法确定所添加的核心线程数 public MyThreadPool(int n) { for (int i = 0; i < n; i++) { Worker worker = new Worker(queue); //这是准备好了 worker.start(); //只有进入了start线程才被创好 workers.add(worker); //添加到链表上 } } //创建一个方法添加任务到队列中 public void submit(Runnable runnable){ try { queue.put(runnable); } catch (InterruptedException e) { e.printStackTrace(); } } } public class Demo12 { public static void main(String[] args) { MyThreadPool pool = new MyThreadPool(10); for (int i = 0; i < 20; i++) { pool.submit(new Runnable() { @Override public void run() { System.out.println("嗨,mythreadpool"); } }); } } }
测试结果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。