浅谈Java获得多线程的返回结果方式(3种)
作者:计科11231 发布时间:2023-04-02 05:37:36
一:Java创建线程方式
继承Thread类或者实现Runnable接口。
但是Runnable 的 run() 方法是不带返回值的,那如果我们需要一个耗时任务在执行完之后给予返回值,应该怎么做呢?
第一种方法:在 Runnable 的实现类中设置一个变量 V,在 run 方法中将其改变为我们期待的结果,然后通过一个 getV() 方法将这个变量返回。
package com.test.thread;
import java.util.*;
import sun.swing.AccumulativeRunnable;
//获得线程的返回结果方式一
/*
*在runnable实现类中设置一个变量x,在run方法中将其改变为我们期待的结果,然后通过一个getX()方法将这个变量返回
*/
public class RunnableTest {
public static void main(String[] args) throws Exception {
System.out.println("使用Runnable获取返回结果");
List<Thread> workers = new ArrayList<>(10);
List<RunnableAcction> tasks = new ArrayList<>(10);
//创建10个线程,每个线程分别负责累加1-10,11-20,.........,91-100
for(int i=0;i<10;i++) {
RunnableAcction task = new RunnableAcction(i*10+1,(i+1)*10);
Thread work = new Thread(task,"累加器线程"+i);
workers.add(work);
tasks.add(task);
work.start();
}
int total = 0;
for(int i = 0;i<workers.size();i++) {
workers.get(i).join();
total += tasks.get(i).getResult();
}
System.out.println("\n累加的结果:"+total);
}
static final class RunnableAcction implements Runnable{
private int a;
public RunnableAcction(int a, int b) {
super();
this.a = a;
this.b = b;
}
private int b;
private int result;
@Override
public void run() {
result = 0;
try {
for(int i=a;i<= b;i++) {
result += i;
Thread.sleep(100);
}
} catch (Exception e) {
// TODO: handle exception
}
System.out.printf("(%s) - 运行结束,结果为 %d\n",Thread.currentThread().getName(),result);
}
public int getResult() {//获取线程返回结果
return result;
}
}
}
第二种方法:使用 Callable 和 FutureTask。
使用 FutureTask 的过程如下:
(1)通过一个 Callable 任务或者一个 Runnable(一开始就指定 result)任务构造 FutureTask;
(2)将 FutureTask 交给 Thread 去运行;
(3)使用 FutureTask 的 get 方法(或者 Thread 的 join 方法)阻塞当前线程直到获得任务的结果。
import java.util.*;
import java.util.concurrent.*;
public class CallableTest {
public static void main(String[] args) throws Exception {
System.out.println("使用 Callable 获得返回结果:");
List<FutureTask<Integer>> futureTasks = new ArrayList<>(10);
// 新建 10 个线程,每个线程分别负责累加 1~10, 11~20, ..., 91~100
for (int i = 0; i < 10; i++) {
AccumCallable task = new AccumCallable(i * 10 + 1, (i + 1) * 10);
FutureTask<Integer> futureTask = new FutureTask<>(task);
futureTasks.add(futureTask);
Thread worker = new Thread(futureTask, "慢速累加器线程" + i);
worker.start();
}
int total = 0;
for (FutureTask<Integer> futureTask : futureTasks) {
total += futureTask.get(); // get() 方法会阻塞直到获得结果
}
System.out.println("累加的结果: " + total);
}
static final class AccumCallable implements Callable<Integer> {
private final int begin;
private final int end;
public AccumCallable(int begin, int end) {
this.begin = begin;
this.end = end;
}
@Override
public Integer call() throws Exception {
int result = 0;
for (int i = begin; i <= end; i++) {
result += i;
Thread.sleep(100);
}
System.out.printf("(%s) - 运行结束,结果为 %d\n",
Thread.currentThread().getName(), result);
return result;
}
}
}
二:FutureTask介绍
FutureTask可用于异步获取执行结果或取消执行任务的场景。通过传入Runnable或者Callable的任务给FutureTask,直接调用其run方法或者放入线程池执行,之后可以在外部通过FutureTask的get方法异步获取执行结果。因此,**FutureTask非常适合用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果。**另外,FutureTask还可以确保即使调用了多次run方法,它都只会执行一次Runnable或者Callable任务,或者通过cancel取消FutureTask的执行等。
一个FutureTask 可以用来包装一个 Callable 或是一个runnable对象。因为FurtureTask实现了Runnable方法,所以一个 FutureTask可以提交(submit)给一个Excutor执行(excution)。
FutureTask执行多任务计算的使用场景:
利用FutureTask和ExecutorService,可以用多线程的方式提交计算任务,主线程继续执行其他任务,当主线程需要子线程的计算结果时,再异步获取子线程的执行结果。
import java.util.*;
import java.util.concurrent.*;
public class FutureTest1 {
public static void main(String[] args) {
Task task = new Task();// 新建异步任务,然后执行futureTask
FutureTask<Integer> future = new FutureTask<Integer>(task) {
// 异步任务执行完成,回调
@Override
protected void done() {
try {
System.out.println("future.done():" + get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
};
// 创建线程池(使用了预定义的配置)
ExecutorService executor = Executors.newCachedThreadPool();
executor.execute(future);
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
// 可以取消异步任务
// future.cancel(true);
try {
// 阻塞,等待异步任务执行完毕-获取异步任务的返回值
System.out.println("future.get():" + future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
// 异步任务
static class Task implements Callable<Integer> {
// 返回异步任务的执行结果
@Override
public Integer call() throws Exception {
int i = 0;
for (; i < 10; i++) {
try {
System.out.println("异步任务:"+Thread.currentThread().getName() + "_" + i);
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return i;
}
}
}
参考文章:
https://blog.csdn.net/chenliguan/article/details/54345993
https://blog.csdn.net/linchunquan/article/details/22382487
https://segmentfault.com/a/1190000007767231
来源:https://blog.csdn.net/jike11231/article/details/106761452
猜你喜欢
- 返回值转成JSONString的处理主要需求描述有些返回值中的null需要转换成“”或[],另外有些
- PathVariable 映射 URL 绑定的占位符带占位符的 URL 是 Spring3.0 新增的功能,该功能在SpringMVC 向
- 在实际项目中,在处理较大的文件时,常常将文件拆分为多个子文件进行处理,最后再合并这些子文件。下面就为各位介绍下Java中合并多个文件的方法。
- 一、前言若使用本机存储来存放文件资源核心实现过程:上传文件,保存文件(本地磁盘)返回文件HTTP访问服务器路径给前端,进行效果展示二、储备服
- 在Java中创建一个线程有两种方法:继承Thread类和实现Runnable接口。下面通过两个例子来分析两者的区别:1)继承Thread类p
- 先看MVC模式流程图(其实MVC设计模式就是java中的model2。): &nb
- 一、输入输出流对象cout:标准输出流cerr:标准出凑 和cout(只是用于如果是错误时要输出的)cin :&nb
- 1.查找概述查找表: 所有需要被查的数据所在的集合,我们给它一个统称叫查找表。查找表(Search Table)是由同一类型的数据元素(或记
- List集合相信大家在开发过程中几乎都会用到。有时候难免会遇到集合里的数据是重复的,需要进行去除。然而,去重方式有好几种方式,你用的是哪种方
- 使用Collections.sort对中文进行排序使用collections.sort(List list, Comparator <
- 本文实例讲述了Android桌面组件App Widget用法。分享给大家供大家参考。具体如下:Android开发应用除了程序应用,还有App
- 如下所示本来 bookService的引用一直是null。导致每次测试都报空指针异常。然后现在继承相应的 ApplicationTests类
- 本文实例为大家分享了C#实现简单串口通讯的具体代码,供大家参考,具体内容如下参数设置界面代码:using System;using Syst
- 背景环境已学习java基础,html,css,js,jquery,bootstrap,layui,maven,servlet和jsp,刚进入
- Message的创建消息Message一般不支持大家直接通过new的方式进行创建的,因为Message作为Android系统中使用频率非常高
- 日志输出是所有系统必备的,很多开发人员可能因为常常使用log4j而忽视了JDK logging模块,两者之间是否有联系?是怎样的联系?JDK
- 把char数组转换成String调用reverseStr()传入一个字符串"let’s"
- 工厂模式Spring中bean的创建,默认是框架利用反射new出来的bean实例。有时候也会有一些复杂的情况。假设有一个飞机,属性如下,现在
- 本文将介绍使用Spring Boot集成Mybatis并实现主从库分离的实现(同样适用于多数据源)。延续之前的Spring Boot 集成M
- 在java中如果我们需要遍历集合并删除其中的某些元素时,例如对于List来说,我们有三种办法。1. 普通的for循环遍历并删除public