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

网友投稿 676 2022-12-04


浅谈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 workers = new ArrayList<>(10);

List 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.get(i).join();

total += taskstdqABtIXt.get(i).getResutdqABtIXtlt();

}

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> 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 futureTask = new FutureTask<>(task);

futureTasks.add(futureTask);

Thread worker = new Thread(futureTask, "慢速累加器线程" + i);

worker.start();

}

int total = 0;

for (FutureTask futureTask : futureTasks) {

total += futureTask.get(); // get() 方法会阻塞直到获得结果

}

System.out.println("累加的结果: " + total);

}

static final class AccumCallable implements Callable {

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 future = new FutureTask(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(tdqABtIXttrue);

try {

// 阻塞,等待异步任务执行完毕-获取异步任务的返回值

System.out.println("future.get():" + future.get());

} catch (InterruptedException e) {

e.printStackTrace();

} catch (ExecutionException e) {

e.printStackTrace();

}

}

// 异步任务

static class Task implements Callable {

// 返回异步任务的执行结果

@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

workers.get(i).join();

total += taskstdqABtIXt.get(i).getResutdqABtIXtlt();

}

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> 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 futureTask = new FutureTask<>(task);

futureTasks.add(futureTask);

Thread worker = new Thread(futureTask, "慢速累加器线程" + i);

worker.start();

}

int total = 0;

for (FutureTask futureTask : futureTasks) {

total += futureTask.get(); // get() 方法会阻塞直到获得结果

}

System.out.println("累加的结果: " + total);

}

static final class AccumCallable implements Callable {

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 future = new FutureTask(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(tdqABtIXttrue);

try {

// 阻塞,等待异步任务执行完毕-获取异步任务的返回值

System.out.println("future.get():" + future.get());

} catch (InterruptedException e) {

e.printStackTrace();

} catch (ExecutionException e) {

e.printStackTrace();

}

}

// 异步任务

static class Task implements Callable {

// 返回异步任务的执行结果

@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


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:mybatis实现图书管理系统
下一篇:Java使用路径通配符加载Resource与profiles配置使用详解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~