Java ExecutorService 四种线程池的例子

本贴最后更新于 2317 天前,其中的信息可能已经时移世易

new Thread()方式

执行一个异步任务,我们可以这样做

new Thread(new Runnable() {
    
	@Override
	public void run() {
	    System.out.println("ThreadName:"+Thread.currentThread().getName());
	}
}).start();

以上方式是可以实现的,但是存在诸多弊端:

  1. 每次都重新 new Thread 新建对象耗费性能;
  2. 缺乏统一管理,并发情况下可能无休止的创建线程,随时可能 oom;
  3. 无法灵活执行线程,如定时、公平、中断等;
  4. 针对耗时较短的异步行为,浪费资源及时间(如下图)
    Thread 生命周期
    以上我们可以看到,真正的运行状态其实只占整个 Thread 生命周期的一小部分,如果只是为了执行一个耗时或占用资源较小的操作,可能开启线程的消耗比线程工作的周期还要长。
    相比 new Thread,Java 提供了四种线程池可用
  • Executors.newCachedThreadPool(); //可伸缩线程池
  • Executors.newFixedThreadPool(5); //固定数量线程池
  • Executors.newSingleThreadExecutor(); //单一线程池
  • Executors.newScheduledThreadPool(5); //可定时执行线程池
    其实还有一种 single 和 schedule 的结合体
  • Executors.newSingleThreadScheduledExecutor();
  1. newCachedThreadPool
    创建一个可伸缩的缓存线程,如果线程池长度超过需要处理的长度,则收回部分线程,如果没有可收回的,就创建新线程,代码如下
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
    final int index = i;

  cachedThreadPool.execute(new Runnable() {
  	  @Override
  	  public void run() {

  		  try {
  			  Thread.sleep(index * 1000);
  			  System.out.println(Thread.currentThread().getName());
  		  } catch (InterruptedException e) {
  			  e.printStackTrace();
  		  }
  	  }
    });
}
cachedThreadPool.shutdown();

结果如下,当需要执行第 7 个的时候,重复使用了线程 1

pool-1-thread-1
pool-1-thread-2
pool-1-thread-3
pool-1-thread-4
pool-1-thread-5
pool-1-thread-6
pool-1-thread-1
pool-1-thread-7
pool-1-thread-8
pool-1-thread-9
  1. newFixedThreadPool
    创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。示例代码如下:
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4);
for (int i = 0; i < 20; i++) {
    final int index = i;
    fixedThreadPool.execute(new Runnable() {

  	  @Override
  		  public void run() {
  			  try {
  				  System.out.println(Thread.currentThread().getName());
  				  Thread.sleep(2000);
  			  } catch (InterruptedException e) {
  				  // TODO Auto-generated catch block
  				  e.printStackTrace();
  			  }
  		  }
    });
}
fixedThreadPool.shutdown();

因为线程池大小为 4 个,每个任务输出后等待 2 秒,所以每次会打印 4 个线程名字。
定长线程池大小最好是根据业务需求和机器资源配置进行设置,选择一个合适的数字,而不是随意想写多少就写多少。

  1. newScheduledThreadPool

    创建一个定长线程池,支持定时延期及周期性任务执行。代码如下:
    延期 3S 执行

    ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
    scheduledThreadPool.schedule(new Runnable() {
    
    	@Override
    	public void run() {
    		System.out.println("delay 3 seconds");
    	}
    }, 3, TimeUnit.SECONDS);
    

    首次延期 1S,然后每 3S 执行一次,倒计时 3 次之后,则退出定时器

    CountDownLatch countDownLatch = new CountDownLatch(3);
    ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
    scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
    
    	@Override
    	public void run() {
    		System.out.println("delay 3 seconds");
    		countDownLatch.countDown();
    	}
    }, 1,3, TimeUnit.SECONDS);
    try {
    	System.out.println("开始等待倒计时...");
    	countDownLatch.await();
    } catch (InterruptedException e) {
    	e.printStackTrace();
    }
    System.out.println("倒计时结束");
    if (countDownLatch.getCount() == 0L) {
    	scheduledThreadPool.shutdown();
    }
    
  2. newSingleThreadExecutor
    创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务

    ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
    for (int i = 0; i < 10; i++) {
    	singleThreadExecutor.execute(new Runnable() {
    
    		@Override
    		public void run() {
    			try {
    				System.out.println(Thread.currentThread().getName());
    				Thread.sleep(2000);
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    	});
    }
    

    会按照顺序依次执行。

  • 线程
    122 引用 • 111 回帖 • 3 关注
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3187 引用 • 8213 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • someone

    😜 😜 😜

  • Wilder

    我居然都知道哈哈哈

  • someone

    整理的都是基础😂

推荐标签 标签

  • 黑曜石

    黑曜石是一款强大的知识库工具,支持本地 Markdown 文件编辑,支持双向链接和关系图。

    A second brain, for you, forever.

    15 引用 • 122 回帖
  • Hadoop

    Hadoop 是由 Apache 基金会所开发的一个分布式系统基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。

    86 引用 • 122 回帖 • 625 关注
  • OpenStack

    OpenStack 是一个云操作系统,通过数据中心可控制大型的计算、存储、网络等资源池。所有的管理通过前端界面管理员就可以完成,同样也可以通过 Web 接口让最终用户部署资源。

    10 引用 • 4 关注
  • DevOps

    DevOps(Development 和 Operations 的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。

    47 引用 • 25 回帖
  • RYMCU

    RYMCU 致力于打造一个即严谨又活泼、专业又不失有趣,为数百万人服务的开源嵌入式知识学习交流平台。

    4 引用 • 6 回帖 • 51 关注
  • CSS

    CSS(Cascading Style Sheet)“层叠样式表”是用于控制网页样式并允许将样式信息与网页内容分离的一种标记性语言。

    198 引用 • 550 回帖
  • PWA

    PWA(Progressive Web App)是 Google 在 2015 年提出、2016 年 6 月开始推广的项目。它结合了一系列现代 Web 技术,在网页应用中实现和原生应用相近的用户体验。

    14 引用 • 69 回帖 • 154 关注
  • Oracle

    Oracle(甲骨文)公司,全称甲骨文股份有限公司(甲骨文软件系统有限公司),是全球最大的企业级软件公司,总部位于美国加利福尼亚州的红木滩。1989 年正式进入中国市场。2013 年,甲骨文已超越 IBM,成为继 Microsoft 后全球第二大软件公司。

    105 引用 • 127 回帖 • 382 关注
  • CSDN

    CSDN (Chinese Software Developer Network) 创立于 1999 年,是中国的 IT 社区和服务平台,为中国的软件开发者和 IT 从业者提供知识传播、职业发展、软件开发等全生命周期服务,满足他们在职业发展中学习及共享知识和信息、建立职业发展社交圈、通过软件开发实现技术商业化等刚性需求。

    14 引用 • 155 回帖
  • 运维

    互联网运维工作,以服务为中心,以稳定、安全、高效为三个基本点,确保公司的互联网业务能够 7×24 小时为用户提供高质量的服务。

    149 引用 • 257 回帖
  • Swift

    Swift 是苹果于 2014 年 WWDC(苹果开发者大会)发布的开发语言,可与 Objective-C 共同运行于 Mac OS 和 iOS 平台,用于搭建基于苹果平台的应用程序。

    36 引用 • 37 回帖 • 529 关注
  • 以太坊

    以太坊(Ethereum)并不是一个机构,而是一款能够在区块链上实现智能合约、开源的底层系统。以太坊是一个平台和一种编程语言 Solidity,使开发人员能够建立和发布下一代去中心化应用。 以太坊可以用来编程、分散、担保和交易任何事物:投票、域名、金融交易所、众筹、公司管理、合同和知识产权等等。

    34 引用 • 367 回帖
  • Ant-Design

    Ant Design 是服务于企业级产品的设计体系,基于确定和自然的设计价值观上的模块化解决方案,让设计者和开发者专注于更好的用户体验。

    17 引用 • 23 回帖
  • Google

    Google(Google Inc.,NASDAQ:GOOG)是一家美国上市公司(公有股份公司),于 1998 年 9 月 7 日以私有股份公司的形式创立,设计并管理一个互联网搜索引擎。Google 公司的总部称作“Googleplex”,它位于加利福尼亚山景城。Google 目前被公认为是全球规模最大的搜索引擎,它提供了简单易用的免费服务。不作恶(Don't be evil)是谷歌公司的一项非正式的公司口号。

    49 引用 • 192 回帖 • 1 关注
  • BND

    BND(Baidu Netdisk Downloader)是一款图形界面的百度网盘不限速下载器,支持 Windows、Linux 和 Mac,详细介绍请看这里

    107 引用 • 1281 回帖 • 27 关注
  • 招聘

    哪里都缺人,哪里都不缺人。

    190 引用 • 1057 回帖
  • Gitea

    Gitea 是一个开源社区驱动的轻量级代码托管解决方案,后端采用 Go 编写,采用 MIT 许可证。

    4 引用 • 16 回帖 • 5 关注
  • iOS

    iOS 是由苹果公司开发的移动操作系统,最早于 2007 年 1 月 9 日的 Macworld 大会上公布这个系统,最初是设计给 iPhone 使用的,后来陆续套用到 iPod touch、iPad 以及 Apple TV 等产品上。iOS 与苹果的 Mac OS X 操作系统一样,属于类 Unix 的商业操作系统。

    85 引用 • 139 回帖 • 1 关注
  • 安全

    安全永远都不是一个小问题。

    199 引用 • 816 回帖 • 1 关注
  • Flume

    Flume 是一套分布式的、可靠的,可用于有效地收集、聚合和搬运大量日志数据的服务架构。

    9 引用 • 6 回帖 • 629 关注
  • Typecho

    Typecho 是一款博客程序,它在 GPLv2 许可证下发行,基于 PHP 构建,可以运行在各种平台上,支持多种数据库(MySQL、PostgreSQL、SQLite)。

    12 引用 • 65 回帖 • 437 关注
  • 代码片段

    代码片段分为 CSS 与 JS 两种代码,添加在 [设置 - 外观 - 代码片段] 中,这些代码会在思源笔记加载时自动执行,用于改善笔记的样式或功能。

    用户在该标签下分享代码片段时需在帖子标题前添加 [css] [js] 用于区分代码片段类型。

    69 引用 • 372 回帖
  • IDEA

    IDEA 全称 IntelliJ IDEA,是一款 Java 语言开发的集成环境,在业界被公认为最好的 Java 开发工具之一。IDEA 是 JetBrains 公司的产品,这家公司总部位于捷克共和国的首都布拉格,开发人员以严谨著称的东欧程序员为主。

    180 引用 • 400 回帖
  • Sym

    Sym 是一款用 Java 实现的现代化社区(论坛/BBS/社交网络/博客)系统平台。

    下一代的社区系统,为未来而构建

    524 引用 • 4601 回帖 • 700 关注
  • Node.js

    Node.js 是一个基于 Chrome JavaScript 运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用。Node.js 使用事件驱动, 非阻塞 I/O 模型而得以轻量和高效。

    139 引用 • 269 回帖 • 43 关注
  • Latke

    Latke 是一款以 JSON 为主的 Java Web 框架。

    71 引用 • 535 回帖 • 787 关注
  • Android

    Android 是一种以 Linux 为基础的开放源码操作系统,主要使用于便携设备。2005 年由 Google 收购注资,并拉拢多家制造商组成开放手机联盟开发改良,逐渐扩展到到平板电脑及其他领域上。

    334 引用 • 323 回帖