惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Martin Fowler
Martin Fowler
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
博客园 - 聂微东
IT之家
IT之家
GbyAI
GbyAI
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Y
Y Combinator Blog
博客园 - 【当耐特】
The Cloudflare Blog
宝玉的分享
宝玉的分享
罗磊的独立博客
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
V
Visual Studio Blog
小众软件
小众软件
博客园_首页
Last Week in AI
Last Week in AI
J
Java Code Geeks
V
V2EX
雷峰网
雷峰网
Apple Machine Learning Research
Apple Machine Learning Research
阮一峰的网络日志
阮一峰的网络日志
腾讯CDC
博客园 - 司徒正美
Engineering at Meta
Engineering at Meta
The GitHub Blog
The GitHub Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
D
DataBreaches.Net
博客园 - 三生石上(FineUI控件)
MyScale Blog
MyScale Blog
云风的 BLOG
云风的 BLOG
The Register - Security
The Register - Security
M
MIT News - Artificial intelligence
Microsoft Azure Blog
Microsoft Azure Blog
T
The Blog of Author Tim Ferriss
N
Netflix TechBlog - Medium
F
Full Disclosure
B
Blog
H
Help Net Security
C
Check Point Blog
WordPress大学
WordPress大学
人人都是产品经理
人人都是产品经理
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Jina AI
Jina AI
酷 壳 – CoolShell
酷 壳 – CoolShell
Blog — PlanetScale
Blog — PlanetScale
L
LangChain Blog
P
Proofpoint News Feed
D
Docker
Microsoft Security Blog
Microsoft Security Blog

技术改变视野

为程序员、设计师打造的摸鱼社区:摸鱼派! - 技术改变视野 大白话 | Java初学指♂男:“说说初学的误区与死结”( 壹 | 反射与Field ) - 技术改变视野 大白话之耦合性:什么是耦合性和内聚性?用编程语言实例讲解! - 技术改变视野 🎨 适用于 Solo / Bolo 的清新高级主题 —— Sakura | 移植自 WordPress 主题 - 技术改变视野 我在 GitHub 上的开源项目 - 技术改变视野 为IDEA/Git配置GPG密钥,点亮GitHub Verified Commit标识 - 技术改变视野 从 SpringMVC 转为使用 SpringBoot —— 手把手带你使用 Intellij IDEA 最快速地搭建 SpringBoot+MyBatis(无 XML)+Thymeleaf - 技术改变视野 无题 - 技术改变视野 年轻人的第一辆京牌电动车 - 技术改变视野 我们忙碌且漫长的一生,有多久是为自己而活? - 技术改变视野 一个最简单的实例理解Semaphore在Java中的作用 - 技术改变视野 说说《后浪》 - 技术改变视野 离线使用 Google Fonts:让你的网站更精致 | goofoffline 神器,一键下载生成离线字体库! - 技术改变视野 实例带你学会简单的Java Thread多线程 - 技术改变视野 一个实例理解Java的接口(interface)用处与用法 - 技术改变视野 一个实例带你理解JavaBean - 技术改变视野 WebFilter-SpringBoot过滤器注解实例讲解 - 技术改变视野 实例带你搞懂Java多线程&&线程池之(壹):线程池与多线程的关系和区别 - 技术改变视野 实例带你获取多线程Thread的返回值之 (壹) - Callable的运行 - 技术改变视野 实例带你获取多线程Thread的返回值之 (贰) - Callable配合线程池返回数据 - 技术改变视野 一个实例理解Java Runnable多线程用处与用法 - 技术改变视野 从零开始OpenSSL之 (壹) - 使用genrsa、rsa、rsautl生成公私钥 - 技术改变视野 从零开始 OpenSSL 之 (贰) - 使用 rsautl 解密文件 - 技术改变视野 大白话之Docker(壹):快速入门&&简单官方实例 - 技术改变视野 大白话之Docker(贰):简单部署一个Tomcat服务并发布内容 - 技术改变视野 大白话之从零讲解DVWA(壹)-SQL注入(SQL Injection) Low Level - 技术改变视野 大白话之从零讲解DVWA(贰)-SQL注入(SQL Injection) Medium/High Level - 技术改变视野 Java日志插件-Slog4J下载 - 技术改变视野 大白话之必会Java Atomic | 线程一点也不安全(一):比自增和synchronized更快速、靠谱的原子操作(调用C语言) - 技术改变视野 Log-MySQL root用户登录后无法查看数据库全部表/正常访问数据库 Access denied for user 'root'@'localhost' to database - 技术改变视野 大白话之Docker(叁):制作一个运行Tomcat服务端的Docker镜像 - 技术改变视野 Github仅保留指定文件/文件夹当前Commit,删除所有历史记录,清除「敏感信息」 - 技术改变视野 将Tomcat、MySQL从Linux迁移到Windows的心路历程(干货):令人恐惧的字符编码 - 技术改变视野 Spring: java.lang.NoSuchMethodError: clearCache | ClassNotFoundException | Error during artifact deployment 思路及解决办法 - 技术改变视野 大白话之Java反射-初学最迷的概念:能干啥?咋用? - 技术改变视野 大白话之Java面向接口编程:最“正经”的中文实例讲解,看不懂来打我! - 技术改变视野 大白话 | 课堂实践:使用Iterator对数组进行遍历 - 技术改变视野 大白话之fail-fast | fail-safe:为什么会有这个机制?它有什么作用? - 技术改变视野 刨根问底 | 大白话:在使用注解后,框架是怎么知道你哪个方法使用了注解的?用@RequestMapping注解举例详解! - 技术改变视野 大白话之必会Java Atomic | 线程一点也不安全(二):Atomic的ABA问题会导致什么情况?如何解决? - 技术改变视野 随笔 | 奇淫技巧 | Java:记return和短路运算符的妙用 - 技术改变视野 随笔 | Tomcat:续-从Linux迁移到Windows编码问题彻底解决 - 技术改变视野 大白话之AutoClosable接口 | try-with-resources:JDK1.7的新特性,提高重复回收效率 - 技术改变视野 大白话之Java多线程join方法:开局一张图,试学一分钟,你就费和我一样,理解介个方法 - 技术改变视野 大白话之Java Stream流:将类数组流化,便捷批量修改,通俗讲解! - 技术改变视野 Java 困扰三周の问题:使用byte[]或skip()方法读取字节流Stream文件尾部多/少/缺字节解决方法 - 技术改变视野 大白话之Java级联调用:一个类,一条语句,同时调用好几个方法,串成一串 - 技术改变视野
实例带你搞懂Java多线程&&线程池之(贰):简单的线程池应用 - 技术改变视野
adlered · 2019-12-09 · via 技术改变视野

前言

这篇文章的代码非常简单,代码后的实验要求一定不要忽略,你一定能理解线程池的算法。

如没看过第一章,请先点我跳转

套用代码

打开你的IDE,并新建一个类,将下方代码拷贝:

 1import java.lang.reflect.Executable;
 2import java.util.concurrent.ExecutorService;
 3import java.util.concurrent.Executors;
 4
 5public class TestThreadPool {
 6    ExecutorService executorService = Executors.newFixedThreadPool(2);
 7    public static void main(String[] args) {
 8        //实例化类
 9        TestThreadPool testThreadPool = new TestThreadPool();
10        //调用动态方法
11        testThreadPool.threadPool();
12    }
13
14    public void threadPool() {
15        Thread1 thread1 = new Thread1();
16        Thread2 thread2 = new Thread2();
17        for (int i = 0; i < 3; i++) {
18            System.out.println("线程池已提交:" + i);
19            executorService.execute(thread1);
20            executorService.execute(thread2);
21        }
22        //executorService.shutdown();
23        //executorService.shutdownNow();
24    }
25}
26
27/**
28 * 线程1
29 */
30class Thread1 implements Runnable {
31    @Override
32    public void run() {
33        System.out.println("WORKING ON THREAD 1");
34        try {
35            Thread.sleep(500);
36        } catch (Exception e) {}
37    }
38}
39
40/**
41 * 线程2
42 */
43class Thread2 implements Runnable {
44    @Override
45    public void run() {
46        System.out.println("WORKING ON THREAD 2");
47        try {
48            Thread.sleep(500);
49        } catch (Exception e) {}
50    }
51}

此时有三个类被定义,其中Thread1Thread2为两个线程的定义。

运行项目

现在运行你的项目,运行结果如下:

1线程池已提交:0
2WORKING ON THREAD 1
3线程池已提交:1
4WORKING ON THREAD 2
5线程池已提交:2
6WORKING ON THREAD 1
7WORKING ON THREAD 2
8WORKING ON THREAD 1
9WORKING ON THREAD 2

阅读代码,在threadPool中我们将线程以execute()提交到了线程池,而通过for循环可以知道共循环提交了三次线程,其中每次分别提交了两个线程。

关闭线程池

你可能发现了,线程池在执行完毕后程序并没有结束,需要手动结束。
现在,将注释掉的executorService.shutdown()取消注释,再次运行,你会发现程序在执行线程池后线程池自动进行了自销毁且程序自动关闭。

1线程池已提交:0
2WORKING ON THREAD 1
3线程池已提交:1
4WORKING ON THREAD 2
5线程池已提交:2
6WORKING ON THREAD 1
7WORKING ON THREAD 2
8WORKING ON THREAD 1
9WORKING ON THREAD 2

现在,重新注释掉executorService.shutdown(),并取消注释executorService.shutdownNow(),运行程序:

1线程池已提交:0
2线程池已提交:1
3WORKING ON THREAD 1
4线程池已提交:2
5WORKING ON THREAD 2

可以看到的是,线程池在没有执行完毕的情况下就终止了程序的运行。这是因为:

1        executorService.shutdown();
2        executorService.shutdownNow();

shutdown()方法就像你点击了电脑的“关机”按钮一样,它不会立即关闭,而是等待未执行完毕的任务全部执行完毕之后才会关闭线程池。

shutdownNow()方法是无视线程池的状态,强制关闭线程池。

调整线程池大小

在代码的最上方,你可以看到:

1ExecutorService executorService = Executors.newFixedThreadPool(2);

其中,我们将newFixedThreadPool(2)拆分来看:

线程池集合

newFixedThreadPool()是Executors(线程池集合)中的一种线程池,在Executors类中共有4种线程池可供选择:

1newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。  
2newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。  
3newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。  
4newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

而我们使用的newFixedThreadPool线程池便是一种定长线程池,它在运行时有如下特性:

1每次只同时运行指定数量的线程,多出的线程会排队等候,直至前面的线程执行完毕再执行。

定义线程池

再来看2,正如你所料的一样,它表示该线程池每次同时只能运行2个线程,其它超出的线程必须排队等候执行完毕。

后语

现在,相信你已经对线程池有了大概的了解了。下一章我们将细说线程池的定义方式。