线程池
来源:互联网 发布:策略经营单机手游 知乎 编辑:程序博客网 时间:2024/05/29 19:31
概述
程序启动一个新线程成本是比较高的,因为它涉及到要与操作系统进行交互。而使用线程池可以很好的提高性能,尤其是当程序中要创建大量生存期很短的线程时,更应该考虑使用线程池。
线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。
使用方式
Java通过Executors提供四种线程池,分别为:
newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
带缓存的线程池
public static void main(String[] args) { ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) { final int nIndex = i; try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } cachedThreadPool.execute(new Runnable() { public void run() { System.out.println(Thread.currentThread().getName() + " " + nIndex); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); // 结束线程 cachedThreadPool.shutdown(); }}
首先程序第一次执行到new Runnable()时候创建了一个线程(thread-1,图中第一行),第一个线程打印信息结束后开始进入1秒的睡眠。
然后,第二个次new Runnable()时候由于第二次到达这里的时间只经过了500毫秒时间,此时,第一个线程还正在睡眠中,这时线程池当前是没有空闲的线程,所以,就创建了第二个线程(thread-2,图中第二行)。
然后,第三次走到new Runnable()时候有经过了500毫秒的时间,此时第一个线程已经完成了睡眠退出了运行,而此时,线程池判断已经又一个线程对象是空闲的了,所以就复用这个线程来执行新的Runnable接口实现对象,所以这里没有直接出现thread-3而还是thread-1。
最后,出现thread-3的时候也是一样的是因为刚好thread-1和thread-2都在睡眠没有释放资源所造成的。
固定长度的线程池
public static void main(String[] args) { ExecutorService cachedThreadPool = Executors.newFixedThreadPool(3); for (int i = 0; i < 10; i++) { final int nIndex = i; cachedThreadPool.execute(() -> { System.out.println(Thread.currentThread().getName() + " " + nIndex); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }); } cachedThreadPool.shutdown();}
无论new Runnable()都始终只有3个线程。定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()。
延时或定时线程池
线程池还可以延时或者定期发送的方式执行,这种线程池也是固定长度的线程池,代码如下:
// 延迟启动public static void main(String[] args) { ScheduledExecutorService ses = Executors.newScheduledThreadPool(5); for (int i = 0; i < 10; i++) { ses.schedule(new Runnable() { @Override public void run() { System.out.println("延迟3秒"); } }, 3, TimeUnit.SECONDS); } // ses.shutdown();}// 定时启动public static void main(String[] args) { ScheduledExecutorService ses = Executors.newScheduledThreadPool(5); for (int i = 0; i < 10; i++) { ses.scheduleAtFixedRate(new Runnable() { @Override public void run() { System.out.println("1秒后每三秒执行一次 " + Thread.currentThread().getName()); } }, 1, 3, TimeUnit.SECONDS); } // ses.shutdown();}
单一任务线程池
这种线程只会复用一个工作线程,确保任务是按照顺序依次执行,代码如下:
public static void main(String[] args) { ExecutorService executorService = Executors.newSingleThreadExecutor(); for (int i = 0; i < 10000; i++) { final int nIndex = i; executorService.execute(new Runnable() { @Override public void run() { System.out.println("线程 " + nIndex + " " + Thread.currentThread().getName()); } }); }}
以上是关于线程池使用方式的学习和理解!
- 线程与线程池
- 线程池 线程优先级
- Executor线程,线程池
- 线程、多线程、线程池
- IOS-线程、线程池
- Java线程:线程池
- 线程和线程池
- 线程、多线程、线程池
- 线程、多线程、线程池
- 线程(六)线程池
- ExecutorService(线程池)+线程
- 线程和线程池
- 线程&线程池 简略
- 线程和线程池
- 线程池 线程锁
- 线程、线程池总结
- 线程与线程池
- 线程、锁、线程池
- 机器学习之——单变量线性回归
- CentOS7.3编译安装NodeJS6.10
- 【mybatis】:mybatis中$和#符号的区别与联系
- 计算机网络:端到端原则对互联网的影响与面临的问题
- D_D系统构建-MBR(1)
- 线程池
- AVL树详解&面试题-判断一棵树是否是平衡二叉树
- [paper] Co-CNN
- Centos-Tomcat配置APR
- 线性表
- C# DataSet和DataTable详解
- java 日期转换校验
- Java+Selenium3方法篇24-单选和多选按钮操作
- SQL:结构化查询语言(Structured Query Language)。