实例带你获取多线程 Thread 的返回值之 (贰) - Callable 配合线程池返回数据

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

v2c0741355c0c124d35234eab7c1dbb55bhd.jpg

前言

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

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

回顾

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

拷贝

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

import java.util.ArrayList; import java.util.List; import java.util.concurrent.*; public class TestThreadPool { ExecutorService executorService = Executors.newFixedThreadPool(2); public static void main(String[] args) { //实例化类 TestThreadPool testThreadPool = new TestThreadPool(); //调用动态方法 testThreadPool.threadPool(); } public void threadPool() { Thread1 thread1 = new Thread1(); Thread2 thread2 = new Thread2(); //将Future包装进List,实现添加结果 List<Future> resultList = new ArrayList<Future>(); for (int i = 0; i < 3; i++) { System.out.println("线程池已提交:" + i); Future res1 = executorService.submit(thread1); Future res2 = executorService.submit(thread2); //将获取的结果添加进List resultList.add(res1); resultList.add(res2); } System.out.println("正在关闭线程池..."); executorService.shutdown(); System.out.println("线程池已关闭."); //executorService.shutdownNow(); //线程池运行结束,打印结果 for (int i = 0; i < resultList.size(); i++) { Future future = resultList.get(i); try { System.out.println(future.get()); } catch (InterruptedException | ExecutionException e) {} } } } /** * 线程1 */ class Thread1 implements Callable { @Override public Object call() throws Exception { try { Thread.sleep(500); } catch (Exception e) {} return "本条数据来自线程1"; } } /** * 线程2 */ class Thread2 implements Callable { @Override public Object call() throws Exception { try { Thread.sleep(500); } catch (Exception e) {} return "本条数据来自线程2"; } }

对比

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

区别

定义的两个线程类:

/** * 线程1 */ class Thread1 implements Callable { @Override public Object call() throws Exception { try { Thread.sleep(500); } catch (Exception e) {} return "本条数据来自线程1"; } } /** * 线程2 */ class Thread2 implements Callable { @Override public Object call() throws Exception { try { Thread.sleep(500); } catch (Exception e) {} return "本条数据来自线程2"; } }

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

调用方法

public void threadPool() { Thread1 thread1 = new Thread1(); Thread2 thread2 = new Thread2(); //将Future包装进List,实现添加结果 List<Future> resultList = new ArrayList<Future>(); for (int i = 0; i < 3; i++) { System.out.println("线程池已提交:" + i); Future res1 = executorService.submit(thread1); Future res2 = executorService.submit(thread2); //将获取的结果添加进List resultList.add(res1); resultList.add(res2); } System.out.println("正在关闭线程池..."); executorService.shutdown(); System.out.println("线程池已关闭."); //executorService.shutdownNow(); //线程池运行结束,打印结果 for (int i = 0; i < resultList.size(); i++) { Future future = resultList.get(i); try { System.out.println(future.get()); } catch (InterruptedException | ExecutionException e) {} } }

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

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

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

运行!

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

线程池已提交:0 线程池已提交:1 线程池已提交:2 正在关闭线程池... 线程池已关闭. 本条数据来自线程1 本条数据来自线程2 本条数据来自线程1 本条数据来自线程2 本条数据来自线程1 本条数据来自线程2

后语

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

  • Java

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

    3192 引用 • 8214 回帖 • 2 关注
  • 代码
    467 引用 • 586 回帖 • 9 关注

相关帖子

欢迎来到这里!

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

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