软件编程
位置:首页>> 软件编程>> java编程>> 浅谈Java获得多线程的返回结果方式(3种)

浅谈Java获得多线程的返回结果方式(3种)

作者:计科11231  发布时间:2023-04-02 05:37:36 

标签:Java,多线程,返回结果

一: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

0
投稿

猜你喜欢

  • 在一些音乐类应用中, 经常会展示随着节奏上下起伏的波纹信息, 这些波纹形象地传达了声音信息, 可以提升用户体验, 那么是如何实现的呢? 可以
  • Android仿通话来电界面,供大家参考,具体内容如下简介:开发中需要模拟来电时的通话界面,仿照来电界面实现来电时播放铃声,界面通过动画模拟
  • 推送系统作为通用的组件,存在的价值主要有以下几点会被多个业务项目使用,推送系 * 立维护可降低维护成本推送系统一般都是调用三方api进行推送,
  • 在构建RESTful数据服务过程中,我们定义了controller、repositories,并用一些注解修饰它们,但是到现在为止我们还没执
  • 使用flatMap列出子目录前面已经看到如何列出指定目录下的文件了。我们再来看下如何遍历指定目录的直接子目录(深度为1),先实现一个简单的版
  • 当我们开发spring web应用程序时,对于如 IOException , ClassNotFoundException 之类的检查异常,
  • 前言:JSON 是轻量级的数据交换格式,很常用,尤其是在使用 Ajax 时,在后台将数据封装为 JSON 字符串更是常见。之前在做项目的时候
  • 1. 背景我们都知道,Compose可以使用mutableStateOf和UI进行绑定,改变值之后,就可以改变UI。var value by
  • Android Bitmap和Drawable的对比Bitmap - 称作位图,一般位图的文件格式后缀为bmp,当然编码器也有很多如RGB5
  • 本文实例讲述了Java高级特性之反射机制。分享给大家供大家参考,具体如下:老规矩我们还是先提出几个问题,一门技术必然要能解决一定的问题,才有
  • 悲观锁、乐观锁简介: 悲观锁:同步操作。即用户A在操作某条数据时,为其上锁,限制其他用户操作,用户A操作完成提交事务后其他用户方可
  • Activator.CreateInstance和AssemblyCreateInstance性能测试using System;using
  • 前言:线程安全是并发编程中的重要关注点,造成线程安全问题的主要原因有两点,一是存在共享数据(也称临界资源),二是存在多条线程共同操作共享数据
  • 本文实例为大家分享了Java实现猜拳游戏的具体代码,供大家参考,具体内容如下一、问题简介通过控制台方式实现一个人机对战的猜拳游戏,用户通过输
  • 一个让人赏心悦目的界面对软件来说非常重要,因此图形图像资源也显得非常重要。本讲就要谈一谈Android中处理图形图像的最重要的一个类Draw
  • 本文实例总结了C# XML序列化方法及常用特性。分享给大家供大家参考,具体如下:C#对象XML序列化(一):序列化方法和常用特性.Net F
  • 新建一个txt的文本(代码中读取这个文本文档路径就行,命名随意)里面的内容一行代表一个,因为我是按行来遍历循环读取要屏蔽的关键字.然后用一个
  • 在源码的阅读过程中,可以了解别人实现某个功能的涉及思路,看看他们是怎么想,怎么做的。接下来,我们看看这篇Java源码解析之object的详细
  • 一、解码流程解码流程大致分为以下三个部分,以FFmpge源码下的ffmpeg\doc\examples\decode_audio.c为参考。
  • 在正式的进入主题之前,我们先来了解下深拷贝和前拷贝的概念:浅拷贝:会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝,如果属性是基本
手机版 软件编程 asp之家 www.aspxhome.com