Java利用Future获取多线程的运行结果

Java利用Future获取多线程的运行结果

场景:在实际生活中比如有这么一个需求:需要统计A路的长度和B路长度的总和。

示例一:先测量出来A路的长度,再去测量B路的长度,最后把二者相加;(串行)

示例二:叫一个小弟过来帮忙,自己去测量A路的长度,让小弟去测量B路的长度;(并行)

那么以上这两种示例的测量速度哪个快显而易见,肯定是第二种更快。

示例二中就相当于我们开发中的多线程,线程A和线程B可以同步执行各自的任务,而不是任务B需要等待任务A执行完成后才能开始执行。

Future是什么?

在以上例子中,小弟相当于我们开了一个线程B去执行任务,但是如何才能拿到这个线程的返回值呢?这是就引入了Future接口。

Future是一个接口,用于表示异步计算的结果。它提供了一种获取异步计算结果的方法,可以在计算完成之前等待结果的可用性。Future接口有几个常用的方法,包括isDone()用于判断计算是否完成,get()用于获取计算结果(如果计算已完成),cancel()用于取消计算等。

Future的get()方法

Future的get()方法是一个非常常用方法,用于获取该线程的返回值;

示例代码如下:

ExecutorService executor = Executors.newFixedThreadPool(5);
long start = System.currentTimeMillis();
Future<Integer> future1 = executor.submit(() -> {
    Thread.sleep(3000);
    return 20;
});
// 获取第一个线程的结果
Integer first = future1.get();
Future<Integer> future2 = executor.submit(() -> {
    Thread.sleep(5000);
    return 50;
});
// 假设这里还有一段业务代码
Thread.sleep(5000);
// 获取第二个线程的结果
Integer second = future2.get();
long end = System.currentTimeMillis();
System.out.println("两个线程的执行结果为:" + (first + second));
System.out.println("总耗时:" + (end - start) + "ms");

/**
* 结果
* 两个线程的执行结果为:70
* 总耗时:8058ms
*/

需要注意的是线程池中的线程需要实现Callable接口进行返回结果,否则实现Runable接口是没有返回值的

Future中的get()方法有两个实现,源码如下:

/**
 * @throws CancellationException {@inheritDoc}
 */
public V get() throws InterruptedException, ExecutionException {
    int s = state;
    if (s <= COMPLETING)
        s = awaitDone(false, 0L);
    return report(s);
}

/**
 * @throws CancellationException {@inheritDoc}
 */
public V get(long timeout, TimeUnit unit)
    throws InterruptedException, ExecutionException, TimeoutException {
    if (unit == null)
        throw new NullPointerException();
    int s = state;
    if (s <= COMPLETING &&
        (s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING)
        throw new TimeoutException();
    return report(s);
}

因为get()方法是会阻塞线程直到线程运行结束的,所以为了避免阻塞时间过长,我们可以调用get(long timeout, TimeUnit unit)这个方法来设置一个超时时间,达到超时时间时会抛出TimeoutException()异常。

这也是Future接口的一个弊端,这里可以对上面的代码稍做优化:

ExecutorService executor = Executors.newFixedThreadPool(5);
long start = System.currentTimeMillis();
Future<Integer> future1 = executor.submit(() -> {
    Thread.sleep(3000);
    return 20;
});
Future<Integer> future2 = executor.submit(() -> {
    Thread.sleep(5000);
    return 50;
});
// 假设这里还有一段业务代码
Thread.sleep(5000);
// 获取第一个线程的结果
Integer first = future1.get();
// 获取第二个线程的结果
Integer second = future2.get();
long end = System.currentTimeMillis();
System.out.println("两个线程的执行结果为:" + (first + second));
System.out.println("总耗时:" + (end - start) + "ms");

/**
* 结果
* 两个线程的执行结果为:70
* 总耗时:5038ms
*/

可以看到时间差距差了3s,所以,非必要时不要去调用Future的get()方法取值,Furue的其他方法也是同理

除了get外,还有以下方法:

  1. cancel 方法:取消任务的执行
  2. isDone方法: 判断线程是否执行完毕
  3. isCanaelled 方法: 判断是否被取消

拓展:如果需要判断该线程是否结束,可以调用Futrue的isDone()方法,会返回一个boolean值

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中,多线程获取返回结果的常用方法是使用`Future`和`Callable`接口。 首先,你需要创建一个实现了`Callable`接口的类,该类负责执行具体的任务,并返回结果。例如: ```java import java.util.concurrent.Callable; public class MyCallable implements Callable<Integer> { @Override public Integer call() throws Exception { // 执行具体的任务逻辑 // 返回结果 return 42; } } ``` 然后,你可以使用`ExecutorService`来提交任务获取`Future`对象,它代表了异步计算的结果。例如: ```java import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class Main { public static void main(String[] args) throws Exception { ExecutorService executorService = Executors.newFixedThreadPool(1); // 提交任务获取Future对象 Future<Integer> future = executorService.submit(new MyCallable()); // 在需要结果的地方调用future.get()方法,该方法会阻塞直到任务完成并返回结果 int result = future.get(); System.out.println("结果:" + result); executorService.shutdown(); } } ``` 在上述代码中,我们使用`submit()`方法将`MyCallable`对象提交给线程池,并得到了一个`Future`对象。然后,我们通过调用`get()`方法来获取任务的执行结果。注意,`get()`方法会阻塞当前线程,直到任务完成并返回结果。 这样,你就可以通过多线程获取任务的返回结果了。当然,你也可以通过`Future`对象的其他方法来判断任务是否完成、取消任务等。具体使用方法可以参考Java官方文档。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值