Callable接口是一个线程吗?我无法运行任何东西

时间:2015-12-23 15:00:06

标签: java multithreading threadpool callable

我已经为一个简单的迷宫项目工作了一段时间,我到了需要使用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!");
    }
}

4 个答案:

答案 0 :(得分:3)

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

  

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

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

答案 1 :(得分:2)

问题是str = task.get();

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

  

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

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

答案 2 :(得分:1)

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

答案 3 :(得分:1)

  

我注意到,当可调用类在后台运行时,我似乎无法在后台运行其他任何东西

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

  

现在使用这个界面似乎毫无意义。

我真的不知道你要做什么,但ExecutorServiceCallable的重点是在后台执行任务。

但是&#34;在背景中是什么&#34;意思?这意味着,当新线程执行某项任务时,提交任务的线程可以执行其他操作

看起来像这样:

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()),那么你是对的:使用多个线程是没有意义的。调用线程只是自己执行任务会更简单。