【问题标题】:is Callable interface a thread? i can't run anything while it works可调用接口是线程吗?我不能运行任何东西,而它工作
【发布时间】:2016-03-30 01:09:06
【问题描述】:

我已经为一个简单的 Maze 项目工作了一段时间,我已经到了需要将 Callable 接口用作线程的地步。实现并运行后,我注意到虽然可调用类在后台运行,但我似乎无法在后台执行任何其他操作,例如输入。

我做了一个小项目来强调这个问题,看到当可调用类工作 10 秒时,我不能同时接受任何输入。 这是代码:

主类

public class Main {

    static ExecutorService service = null;
    static Future<String> task = null;

    public static void main(final String[] argv) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("please enter a command");
        String string = in.readLine();
        while (!string.equals("exit")) {
            if (!string.equals("command")) {
                System.out.println("command not found");
            } else {
                service = Executors.newFixedThreadPool(1);
                task = service.submit(new Foo());

                try {
                    final String str;

                    // waits the 10 seconds for the Callable.call to finish.
                    str = task.get(); // this raises ExecutionException if
                                        // thread dies
                    System.out.println(str);
                    service.shutdownNow();
                } catch (final InterruptedException ex) {
                    ex.printStackTrace();
                } catch (final ExecutionException ex) {
                    ex.printStackTrace();
                }
            }
            string = in.readLine();

        }

        //
    }
}

可调用类:

class Foo implements Callable<String> {
    @Override
    public String call() {
        try {
            // sleep for 10 seconds
            Thread.sleep(10 * 1000);
        } catch (final InterruptedException ex) {
            ex.printStackTrace();
        }

        return ("Hello, World!");
    }
}

【问题讨论】:

  • Callable 是一个任务
  • // sleep for 10 seconds Thread.sleep(5 * 1000); 不写评论总比写错cmets好。幸运的是,这一点非常明显。
  • task.get() 等待后台线程完成。 (你可以从下面的两个答案中推断出来,即使他们没有直接说出来。)

标签: java multithreading threadpool callable


【解决方案1】:

Callable 本身不做任何事情。它只是一个约定接口。要使可调用异步,您需要在执行程序中运行它。例如,请参阅https://blogs.oracle.com/CoreJavaTechTips/entry/get_netbeans_6

【讨论】:

    【解决方案2】:

    https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#submit(java.util.concurrent.Callable)

    如果您想立即阻止等待任务,可以使用以下形式的构造 result = exec.submit(aCallable).get();

    这正是你正在做的(阻塞等待任务的主线程)

    【讨论】:

    • 那么,如果我不能同时运行更多线程而这个接口工作,那么使用这个接口有什么好处呢?
    • 您应该使用 executor.submit() 返回的 Future 对象,然后您可以在该元素上调用 isDone() 以了解操作何时完成。当 isDone 返回 true 时,您可以使用 get() 获得结果(总是在 Future 对象上调用)
    【解决方案3】:

    问题是str = task.get();

    根据 JavaDoc for Future#get() (https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#get%28%29):

    如有必要,等待计算完成,然后检索其结果。

    如果你想要 Callable 的结果,你必须等到它完成。

    【讨论】:

    • 好吧,我想我明白了。虽然现在使用这个界面似乎毫无意义,但无论如何我现在明白了这个问题。谢谢大家的帮助
    【解决方案4】:

    我注意到,虽然可调用类在后台运行,但我似乎无法在后台执行任何其他操作

    ...讨论,...问题解释...

    现在用这个界面好像没什么意义了。

    我真的不知道你想做什么,但ExecutorServiceCallable 的全部意义在于在后台执行任务。

    但是“在后台”是什么意思?这意味着,当新线程停止执行某些任务时,提交任务的线程可以执行其他操作

    看起来像这样:

    final ExecutorService executorService = Executors.newFixedThreadPool(NUM_THREADS);
    
    ReturnType doSomethingInTheBackground() {
    
        // create the task object
        Callable<ReturnType> task = () -> doSomething();
    
        // submit the task object
        Future<ReturnType> future = executorService.submit(task);
    
        doSomethingElse();
    
        // wait for the result.
        return future.get();
    }
    
    private ReturnType doSomething() { ... }
    
    private void doSomethingElse() { ... }
    

    doSomethingElse() 电话让这一切变得值得。如果调用线程除了等待结果之外没有其他事情可做(即调用future.get()),那么您是对的:使用多个线程是没有意义的。调用线程自己完成任务会更简单。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-05
      • 2023-03-18
      • 1970-01-01
      • 2019-09-25
      • 1970-01-01
      • 1970-01-01
      • 2015-04-22
      相关资源
      最近更新 更多