我们如何将可调用对象转换为可运行对象

问题描述 投票:0回答:6

我有一个实现可调用接口的类。我想使用 ScheduledExecutorService 接口的 ScheduleAtFixedRate 方法为该类安排任务。然而scheduleAtFixedRate需要一个可运行的对象作为它可以调度的命令。

因此我需要某种方法将可调用对象转换为可运行对象。我尝试了简单的转换,但这不起作用。

示例代码:

package org.study.threading.executorDemo;

import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

class ScheduledExecutionTest implements Callable<String> {

    @Override
    public String call() throws Exception {
        // TODO Auto-generated method stub
        System.out.println("inside the call method");
        return null;
    }

}
public class ScheduledExecution {
    public static void main(String[] args) {
        ScheduledExecutorService sec = Executors.newScheduledThreadPool(10);
        sec.scheduleAtFixedRate(new ScheduledExecutionTest(), 5, 2, TimeUnit.SECONDS);
    }
}
java multithreading runnable callable scheduledexecutorservice
6个回答
12
投票
FutureTask task1 = new FutureTask(Callable<V> callable)

现在这个任务 1 可以运行了,因为:

  1. class FutureTask<V> implements RunnableFuture<V>
  2. RunnableFuture<V> extends Runnable, Future<V>

所以从上面两个关系来看,task1是可运行的并且可以在

Executor.execute(Runnable)
方法中使用


3
投票

假设您确实不需要

Callable
返回任何有用的内容,您可以将 Callable 包装为 Runnable

Runnable run = new Runnable() {
    public void run() {
        try {
            Object o = callable.call();
            System.out.println("Returned " + o);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
};

或在 Java 8 中

Runnable run = () -> {
    try {
        Object o = callable.call();
        System.out.println("Returned " + o);
    } catch (Exception e) {
        e.printStackTrace();
    }
};

这相当混乱,但听起来 Callable 首先应该是 Runnable,而您不必这样做。


2
投票

JDK 有一个 util 方法来解决这个问题:

Runnable runnable = ..
Executors.callable(runnable);

0
投票

为什么不使用类似的东西:

  final Callable<YourType> callable = ...; // Initialize Callable

  Runnable callableAsRunnable = () -> {
     try {
        callable.call();
     } catch (Exception e) {
        // Handle the exception locally or throw a RuntimeException
     }
  };

0
投票

使用 future task ,它同时实现了 Runnable 和 callable ,你不需要修改太多代码。

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/FutureTask.html


0
投票

Callable
转换为
Runnable
的问题是包装可调用对象可能抛出的异常。

Machine Zoo 的

NoException 包对此有很大帮助:

@Test public void testCallableToRunnable () { boolean[] flag = { false }; Callable<String> callable = () -> { flag[0] = true; return "Hello, World"; }; Runnable runnable = Exceptions.sneak ().runnable ( () -> callable.call () ); runnable.run (); Assertions.assertTrue ( flag [ 0 ], "Callable not run!" ); }

sneak()

 欺骗编译器相信没有检查异常,但最终可以抛出此类异常并被正确拦截。 
Exceptions
 类提供了其他选项,例如用 
RuntimeException
 包装已检查的异常。

正如其他人所说,

Executors

有一个助手可以从
Runnable
转换为
Callable
。其他人也说,JDK 没有提供相反的方法的原因可能是,你做错了:如果可调用返回一些结果,也许你应该使用它,如果它可能抛出异常,也许你不应该忽视它。

© www.soinside.com 2019 - 2024. All rights reserved.