当前位置: 首页 > 编程笔记 >

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

左丘成仁
2023-03-14
本文向大家介绍浅谈Java获得多线程的返回结果方式(3种),包括了浅谈Java获得多线程的返回结果方式(3种)的使用技巧和注意事项,需要的朋友参考一下

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

到此这篇关于浅谈Java获得多线程的返回结果方式的文章就介绍到这了,更多相关Java 多线程的返回结果内容请搜索小牛知识库以前的文章或继续浏览下面的相关文章希望大家以后多多支持小牛知识库! 

 类似资料:
  • 本文向大家介绍浅谈Java的两种多线程实现方式,包括了浅谈Java的两种多线程实现方式的使用技巧和注意事项,需要的朋友参考一下 本文介绍了浅谈Java的两种多线程实现方式,分享给大家。具有如下: 一、创建多线程的两种方式 Java中,有两种方式可以创建多线程: 1 通过继承Thread类,重写Thread的run()方法,将线程运行的逻辑放在其中 2 通过实现Runnable接口,实例化Threa

  • 本文向大家介绍浅谈chuck-lua中的多线程,包括了浅谈chuck-lua中的多线程的使用技巧和注意事项,需要的朋友参考一下 chuck-lua支持actor模式的线程模型.可以通过cthread.new创建线程,然后通过cthread.sendmail向线程发送消息. 与skynet这种框架不同,chuck-lua并不提供多线程的任务/消息调度功能,每个线程维护了一个简单的线程邮箱,用于缓存其

  • 本文向大家介绍浅谈java线程join方法使用方法,包括了浅谈java线程join方法使用方法的使用技巧和注意事项,需要的朋友参考一下 本博客简介介绍一下java线程的join方法,join方法是实现线程同步,可以将原本并行执行的多线程方法变成串行执行的 如图所示代码,是并行执行的 打印出来的信息,都是这样的 执行时间:0 线程1:1 线程2:1 线程2:2 线程2:3 线程2:4 线程2:5 线

  • 本文向大家介绍浅谈java多线程 join方法以及优先级方法,包括了浅谈java多线程 join方法以及优先级方法的使用技巧和注意事项,需要的朋友参考一下 join: 当A线程执行到了B线程的.join()方法时,A就会等待。等B线程都执行完,A才会执行。 join可以用来临时加入线程执行。 1、线程使用join方法,主线程就停下,等它执行完,那么如果该线程冻结了,主线程就挂了,这也是为什么线程要

  • 本文向大家介绍浅谈Java HttpURLConnection请求方式,包括了浅谈Java HttpURLConnection请求方式的使用技巧和注意事项,需要的朋友参考一下 一)URL代理请求 ​ 该方式请求有两种代理方式。 方式一:使用该方式代理之后,之后的所有接口都会使用代理请求 方式二:适用于只有部分接口需要代理请求场景 二)无参数GET请求 方法解析: HttpGetUtils.doGe

  • 本文向大家介绍浅谈java的守护线程与非守护线程,包括了浅谈java的守护线程与非守护线程的使用技巧和注意事项,需要的朋友参考一下 最近重新研究Java基础知识,发现以前太多知识知识略略带过了,比较说Java的线程机制,在Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程) ,(PS:以前忽略了)。 估计学过Unix开发但是没有细致学习Java的同学们会