Java中常用的四种线程池
在Java中使用线程池,可以用ThreadPoolExecutor的构造函数直接创建出线程池实例,如何使用参见之前的文章Java线程池构造参数详解。不过,在Executors类中,为我们提供了常用线程池的创建方法。接下来我们就来了解常用的四种:
newFixedThreadPool
首先,看一下这种线程池的创建方法:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
从构造方法可以看出,它创建了一个固定大小的线程池,每次提交一个任务就创建一个线程,直到线程达到线程池的最大值nThreads。线程池的大小一旦达到最大值后,再有新的任务提交时则放入无界阻塞队列中,等到有线程空闲时,再从队列中取出任务继续执行。
那么,如何使用newFixedThreadPool呢?我们来举个例子:
public class OneMoreStudy {
public static void main(String[] args) {
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 5; i++) {
final int index = i;
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
SimpleDateFormat sdf = new SimpleDateFormat(
"HH:mm:ss");
System.out.println("运行时间: " +
sdf.format(new Date()) + " " + index);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
fixedThreadPool.shutdown();
}
}
上面的例子中创建了一个固定大小为3的线程池,然后在线程池提交了5个任务。在提交第4个任务时,因为线程池的大小已经达到了3并且前3个任务在运行中,所以第4个任务被放入了队列,等待有空闲的线程时再被运行。运行结果如下(注意前3个任务和后2个任务的运行时间):
运行时间: 08:09:02 1
运行时间: 08:09:02 2
运行时间: 08:09:02 0
运行时间: 08:09:04 4
运行时间: 08:09:04 3
newCachedThreadPool
首先,看一下这种线程池的创建方法:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
从构造方法可以看出,它创建了一个可缓存的线程池。当有新的任务提交时,有空闲线程则直接处理任务,没有空闲线程则创建新的线程处理任务,队列中不储存任务。线程池不对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。如果线程空闲时间超过了60秒就会被回收。
那么,如何使用newCachedThreadPool呢?我们来举个例子:
public class OneMoreStudy {
public static void main(String[] args) {
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++) {
final int index = i;
cachedThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
SimpleDateFormat sdf = new SimpleDateFormat(
"HH:mm:ss");
System.out.println("运行时间: " +
sdf.format(new Date()) + " " + index);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
cachedThreadPool.shutdown();
}
}
因为这种线程有新的任务提交,就会创建新的线程(线程池中没有空闲线程时),不需要等待,所以提交的5个任务的运行时间是一样的,运行结果如下:
运行时间: 08:45:18 2
运行时间: 08:45:18 1
运行时间: 08:45:18 3
运行时间: 08:45:18 4
运行时间: 08:45:18 0
newSingleThreadExecutor
首先,看一下这种线程池的创建方法:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
从构造方法可以看出,它创建了一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序执行。
那么,如何使用newSingleThreadExecutor呢?我们来举个例子:
public class OneMoreStudy {
public static void main(String[] args) {
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++) {
final int index = i;
singleThreadExecutor.execute(new Runnable() {
@Override
public void run() {
try {
SimpleDateFormat sdf = new SimpleDateFormat(
"HH:mm:ss");
System.out.println("运行时间: " +
sdf.format(new Date()) + " " + index);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
singleThreadExecutor.shutdown();
}
}
因为该线程池类似于单线程执行,所以先执行完前一个任务后,再顺序执行下一个任务,
运行结果如下:
运行时间: 08:54:17 0
运行时间: 08:54:19 1
运行时间: 08:54:21 2
运行时间: 08:54:23 3
运行时间: 08:54:25 4
有的同学可能会质疑:既然类似于单线程执行,那么这种线程池还有存在的必要吗?这里的单线程执行指的是线程池内部,从线程池外的角度看,主线程在提交任务到线程池时并没有阻塞,仍然是异步的。
newScheduledThreadPool
这个方法创建了一个固定大小的线程池,支持定时及周期性任务执行。
首先看一下定时执行的例子:
public class OneMoreStudy {
public static void main(String[] args) {
final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
System.out.println("提交时间: " + sdf.format(new Date()));
scheduledThreadPool.schedule(new Runnable() {
@Override
public void run() {
System.out.println("运行时间: " + sdf.format(new Date()));
}
}, 3, TimeUnit.SECONDS);
scheduledThreadPool.shutdown();
}
}
使用该线程池的schedule方法,延迟3秒钟后执行任务,运行结果如下:
提交时间: 09:11:39
运行时间: 09:11:42
再看一下周期执行的例子:
public class OneMoreStudy {
public static void main(String[] args) {
final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
System.out.println("提交时间: " + sdf.format(new Date()));
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("运行时间: " + sdf.format(new Date()));
}
}, 1, 3, TimeUnit.SECONDS);
Thread.sleep(10000);
scheduledThreadPool.shutdown();
}
}
使用该线程池的scheduleAtFixedRate方法,延迟1秒钟后每隔3秒执行一次任务,运行结果如下:
提交时间: 09:23:20
运行时间: 09:23:21
运行时间: 09:23:24
运行时间: 09:23:27
Java中常用的四种线程池的更多相关文章
- Java通过Executors提供四种线程池
http://cuisuqiang.iteye.com/blog/2019372 Java通过Executors提供四种线程池,分别为:newCachedThreadPool创建一个可缓存线程池,如果 ...
- java自带的四种线程池
java预定义的哪四种线程池? newSingleThreadExexcutor:单线程数的线程池(核心线程数=最大线程数=1) newFixedThreadPool:固定线程数的线程池(核心线程数= ...
- Java 四种线程池newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor
介绍new Thread的弊端及Java四种线程池的使用,对Android同样适用.本文是基础篇,后面会分享下线程池一些高级功能. 1.new Thread的弊端执行一个异步任务你还只是如下new T ...
- Java四种线程池
Java四种线程池newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor 时间:20 ...
- Java四种线程池newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor
1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? Java new Thread(new Runnable() { @Override public void ru ...
- Java 四种线程池的用法分析
1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? new Thread(new Runnable() { @Override public void run() { ...
- Java四种线程池的学习与总结
在Java开发中,有时遇到多线程的开发时,直接使用Thread操作,对程序的性能和维护上都是一个问题,使用Java提供的线程池来操作可以很好的解决问题. 一.new Thread的弊端 执行一个异步任 ...
- Java ExecutorService四种线程池及自定义ThreadPoolExecutor机制
一.Java 线程池 Java通过Executors提供四种线程池,分别为:1.newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收 ...
- Java四种线程池的使用
Java通过Executors提供四种线程池,分别为:newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程.newFixe ...
随机推荐
- SpringBoot + Jpa(Hibernate) 架构基本配置
1.基于springboot-1.4.0.RELEASE版本测试 2.springBoot + Hibernate + Druid + Mysql + servlet(jsp) 一.maven的pom ...
- eclipse导入别的项目后发现jdk版本不一样,该如何解决呢?
当我们导入其他人的项目的时候,发现导入的项目的jdk版本与我们使用电脑上的版本不同,该如何解决呢? 选中项目右键 --> Properties --> Build Path --> ...
- 数据结构与算法(C/C++版)【数组】
第五章<数组> 一.概念 根据数组中存储的数据元素之间的逻辑关系,可以将数组分为 : 一维数组.二维数组.….n维数组.n维数组中,维数 n 的判断依据是:根据数组中为确定元素所在位置使用 ...
- Spring Boot认证:整合Jwt
背景 Jwt全称是:json web token.它将用户信息加密到token里,服务器不保存任何用户信息.服务器通过使用保存的密钥验证token的正确性,只要正确即通过验证. 优点 简洁: 可以通过 ...
- nginx的ngx_http_geoip2模块以精准禁止特定地区IP访问
要求:对网站的信息,比如某个访问节点不想国内或者国外的用户使用,禁止国内或者国外或者精确到某个城市的那种情况. 解决方式:1.Cloudfalre来实现禁止特定国家的ip访问,比较简单,但是需要mon ...
- 微信公众平台开发(57)Emoji表情符号 【转发】
微信公众平台开发(57)Emoji表情符号 微信公众平台开发 微信公众平台开发模式 企业微信公众平台 Emoji表情符号 作者:方倍工作室 地址:http://www.cnblogs.com/tx ...
- vue-cli搭建项目引入jquery和jquery-weui步骤详解
vue简介 Vue.js 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用. Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合 ...
- 爬虫那点事,干就玩了之seleunim
目录 selenium 环境准备 代码环境 开始爬虫 操作js 截图 切换窗口 在当前窗口切换访问地址 管理cookie # 加入战队 微信公众号 # 加入战队 微信公众号 做技术我们最重要的是[做] ...
- day 23
目录 面向对象总复习 面向对象总复习 面向过程编程思想: 核心是过程,过程指的是做事情的步骤,即先干什么再干什么. 基于该编程思想编程,就好比一条流水线,一种机械式的思维方式. 面向对象编程思 ...
- 10月27日Java整理
实验一:凯撒密码 import java.util.Scanner; //zhanxinwu,October,25,2016 public class Addmi { public static vo ...