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

推荐订阅源

J
Java Code Geeks
爱范儿
爱范儿
Attack and Defense Labs
Attack and Defense Labs
量子位
The GitHub Blog
The GitHub Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Scott Helme
Scott Helme
C
CXSECURITY Database RSS Feed - CXSecurity.com
博客园 - 叶小钗
C
Cybersecurity and Infrastructure Security Agency CISA
S
Securelist
S
Schneier on Security
C
Cisco Blogs
B
Blog RSS Feed
Cisco Talos Blog
Cisco Talos Blog
Last Week in AI
Last Week in AI
WordPress大学
WordPress大学
腾讯CDC
酷 壳 – CoolShell
酷 壳 – CoolShell
罗磊的独立博客
Y
Y Combinator Blog
Latest news
Latest news
T
Tailwind CSS Blog
Jina AI
Jina AI
宝玉的分享
宝玉的分享
人人都是产品经理
人人都是产品经理
C
CERT Recently Published Vulnerability Notes
D
Darknet – Hacking Tools, Hacker News & Cyber Security
L
Lohrmann on Cybersecurity
The Cloudflare Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Microsoft Security Blog
Microsoft Security Blog
H
Help Net Security
P
Palo Alto Networks Blog
V
V2EX
博客园_首页
D
Docker
T
Threat Research - Cisco Blogs
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
Vulnerabilities – Threatpost
月光博客
月光博客
D
DataBreaches.Net
Stack Overflow Blog
Stack Overflow Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Know Your Adversary
Know Your Adversary
L
LangChain Blog
The Hacker News
The Hacker News
K
Kaspersky official blog
The Register - Security
The Register - Security
NISL@THU
NISL@THU

技术改变视野

为程序员、设计师打造的摸鱼社区:摸鱼派! - 技术改变视野 大白话 | 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多线程&&线程池之(壹):线程池与多线程的关系和区别 - 技术改变视野 实例带你搞懂Java多线程&&线程池之(贰):简单的线程池应用 - 技术改变视野 实例带你获取多线程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级联调用:一个类,一条语句,同时调用好几个方法,串成一串 - 技术改变视野
实例带你获取多线程Thread的返回值之 (贰) - Callable配合线程池返回数据 - 技术改变视野
adlered · 2019-12-09 · via 技术改变视野

前言

阅读本篇文章,你需要先理解以下知识:

  • 第一章:Callable的使用(点我跳转
  • 多线程Thread的基本使用 (点我跳转
  • 线程池基本知识 (点我跳转
  • extends和implements
  • 重写Override
  • try catch错误处理
  • Java基础知识

回顾

在上一章(点我跳转)我们了解了Callable的基本使用,本次我们将把Callable运用到线程池(点我跳转)中。

拷贝

用你的IDE新建一个项目或类,并将类命名为TestThreadPool,然后将下面的代码替换到类中:

 1import java.util.ArrayList;
 2import java.util.List;
 3import java.util.concurrent.*;
 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        //将Future包装进List,实现添加结果
18        List<Future> resultList = new ArrayList<Future>();
19        for (int i = 0; i < 3; i++) {
20            System.out.println("线程池已提交:" + i);
21            Future res1 = executorService.submit(thread1);
22            Future res2 = executorService.submit(thread2);
23            //将获取的结果添加进List
24            resultList.add(res1);
25            resultList.add(res2);
26        }
27        System.out.println("正在关闭线程池...");
28        executorService.shutdown();
29        System.out.println("线程池已关闭.");
30        //executorService.shutdownNow();
31        //线程池运行结束,打印结果
32        for (int i = 0; i < resultList.size(); i++) {
33            Future future = resultList.get(i);
34            try {
35                System.out.println(future.get());
36            } catch (InterruptedException | ExecutionException e) {}
37        }
38    }
39}
40
41/**
42 * 线程1
43 */
44class Thread1 implements Callable {
45    @Override
46    public Object call() throws Exception {
47        try {
48            Thread.sleep(500);
49        } catch (Exception e) {}
50        return "本条数据来自线程1";
51    }
52}
53
54/**
55 * 线程2
56 */
57class Thread2 implements Callable {
58    @Override
59    public Object call() throws Exception {
60        try {
61            Thread.sleep(500);
62        } catch (Exception e) {}
63        return "本条数据来自线程2";
64    }
65}

对比

和线程池第二章的文章(点我跳转)中的实例代码对比一下,你会发现它们大概是相同的,此时再回顾一下Callable中的实例代码(点我跳转),你会发现这篇是这两篇的结合。

区别

定义的两个线程类:

 1/**
 2 * 线程1
 3 */
 4class Thread1 implements Callable {
 5    @Override
 6    public Object call() throws Exception {
 7        try {
 8            Thread.sleep(500);
 9        } catch (Exception e) {}
10        return "本条数据来自线程1";
11    }
12}
13
14/**
15 * 线程2
16 */
17class Thread2 implements Callable {
18    @Override
19    public Object call() throws Exception {
20        try {
21            Thread.sleep(500);
22        } catch (Exception e) {}
23        return "本条数据来自线程2";
24    }
25}

你会发现它不再使用Runnable了,而是使用了Callable以支持返回数据。并且重写的方法不再是run(),而是call()。我们使用return返回了String类型的字符串。

调用方法

 1public void threadPool() {
 2        Thread1 thread1 = new Thread1();
 3        Thread2 thread2 = new Thread2();
 4        //将Future包装进List,实现添加结果
 5        List<Future> resultList = new ArrayList<Future>();
 6        for (int i = 0; i < 3; i++) {
 7            System.out.println("线程池已提交:" + i);
 8            Future res1 = executorService.submit(thread1);
 9            Future res2 = executorService.submit(thread2);
10            //将获取的结果添加进List
11            resultList.add(res1);
12            resultList.add(res2);
13        }
14        System.out.println("正在关闭线程池...");
15        executorService.shutdown();
16        System.out.println("线程池已关闭.");
17        //executorService.shutdownNow();
18        //线程池运行结束,打印结果
19        for (int i = 0; i < resultList.size(); i++) {
20            Future future = resultList.get(i);
21            try {
22                System.out.println(future.get());
23            } catch (InterruptedException | ExecutionException e) {}
24        }
25    }

该方法仍是使用了同样的线程池,但执行方法使用了submit()而不是execute()。因为execute()方法只支持Runnable,请注意。

我们将Future套入了一个List中,以便异步循环写入每个线程执行后返回的结果。

请仔细阅读调试,这并不难理解。

运行!

现在,运行你的代码,你会看到以下结果:

 1线程池已提交:0
 2线程池已提交:1
 3线程池已提交:2
 4正在关闭线程池...
 5线程池已关闭.
 6本条数据来自线程1
 7本条数据来自线程2
 8本条数据来自线程1
 9本条数据来自线程2
10本条数据来自线程1
11本条数据来自线程2

后语

Java线程与线程池的知识点实际上是很多的。使用多线程是为了拥有更强的性能和更灵活的调用能力,同时也是每个合格的程序员必会的知识点。