Java 如何将参数传递给线程并获得返回值?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20221408/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 00:23:50  来源:igfitidea点击:

How to pass a parameter to a thread and get a return value?

javamultithreading

提问by pmichna

public class CalculationThread implements Runnable {

    int input;
    int output;

    public CalculationThread(int input)
    {
        this.input = input;
    }

    public void run() {
        output = input + 1;
    }

    public int getResult() {
        return output;
    }
}

Somewhere else:

别的地方:

Thread thread = new Thread(new CalculationThread(1));
thread.start();
int result = thread.getResult();

Of course, thread.getResult()doesn't work (it tries to invoke this method from the Threadclass).

当然,thread.getResult()不起作用(它试图从Thread类中调用此方法)。

You get what I want. How can I achieve this in Java?

你得到我想要的。我如何在 Java 中实现这一点?

采纳答案by Andrey Chaschev

This a job for thread pools. You need to create a Callable<R>which is Runnablereturning a value and send it to a thread pool.

这是线程池的工作。您需要创建一个Callable<R>Runnable返回一个值,并将其发送到线程池。

The result of this operation is a Future<R>which is a pointer to this job which will contain a value of the computation, or will not if the job fails.

此操作的结果Future<R>是一个指向此作业的指针,它将包含计算值,如果作业失败则不会。

public static class CalculationJob implements Callable<Integer> {
    int input;

    public CalculationJob(int input) {
        this.input = input;
    }

    @Override
    public Integer call() throws Exception {
        return input + 1;
    }
}

public static void main(String[] args) throws InterruptedException {
    ExecutorService executorService = Executors.newFixedThreadPool(4);

    Future<Integer> result = executorService.submit(new CalculationJob(3));

    try {
        Integer integer = result.get(10, TimeUnit.MILLISECONDS);
        System.out.println("result: " + integer);
    } catch (Exception e) {
        // interrupts if there is any possible error
        result.cancel(true);
    }

    executorService.shutdown();
    executorService.awaitTermination(1, TimeUnit.SECONDS);
}

Prints:

印刷:

result: 4

回答by Silviu Burcea

You are looking for Callable. It's a Runnable on steroids, it can return a result. Check the javadoc:http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Callable.html

您正在寻找可调用的。它是类固醇上的 Runnable,它可以返回结果。检查 javadoc:http: //docs.oracle.com/javase/7/docs/api/java/util/concurrent/Callable.html

Here is a tutorial: http://www.journaldev.com/1090/java-callable-future-example

这是一个教程:http: //www.journaldev.com/1090/java-callable-future-example

回答by Roman C

Use constructor and pass value by reference.

使用构造函数并通过引用传递值。

public CalculationThread(int[] input)

Do you want to pass the value of intto the thread called CalculationThreadyou should create a thread but if you pass a parameter by value the thread can use that value but you can't get the data back. Passing it by reference you can modify the value but not reference in the thread and the reference if it's available to both threads point to the value which is modifiable in both threads. Of cause you code should be synchronized to share the same reference.

您想将 的值传递int给调用的线程CalculationThread吗?您应该创建一个线程,但是如果您按值传递参数,该线程可以使用该值,但您无法取回数据。通过引用传递它,您可以修改该值,但不能修改线程中的引用,如果两个线程都可以使用该引用,则该引用指向在两个线程中均可修改的值。因为您的代码应该同步以共享相同的引用。

回答by bowmore

The accepted answer is great. But it is not the simplest approach. There's no real need to use an ExecutorService if you just want to wait for the result of a thread. You can simply use java.util.concurrent.FutureTask, which is basically a Runnablewrapping a Callablewhich also implements the Futureinterface.

接受的答案很棒。但这不是最简单的方法。如果您只想等待线程的结果,则实际上没有必要使用 ExecutorService。您可以简单地使用java.util.concurrent.FutureTask,它基本上是一个Runnable包装 a Callable,它也实现了Future接口。

So step 1 is still make the calculation a Callable:

所以步骤 1 仍然是计算 a Callable

public class Calculation implements Callable<Integer> {

    private final int input;

    public Calculation(int input) {
        this.input = input;
    }

    @Override
    public Integer call() throws Exception {
        return input + 1;
    }
}

So where you need the asynchronous calculation you can do :

因此,您可以在需要异步计算的地方执行以下操作:

    FutureTask<Integer> task = new FutureTask<>(new Calculation(1561));
    new Thread(task).start();

    // ... do other stuff

    // when I really need the result :

    try {
        int result = task.get(); // this will wait for the task to finish, if it hasn't yet.
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    } catch (ExecutionException e) {
        e.getCause().printStackTrace(); // e.getCause() holds the exception that happened on the calculation thread
    }

What the ExecutorServiceadds is managing a pool of threads to run the task on, but under the hood of an ExecutorService, basically the same thing happens.

什么ExecutorService增加是管理线程池来运行的任务,但的引擎盖下ExecutorService,基本上是同样的事情发生。

回答by Georgy Gobozov

Old school style

老派风格

public class CalculationThread extends Thread {

    int input;
    int output;

    public CalculationThread(int input){
        this.input = input;
    }

    public void run() {
        output = input + 1;
    }

    public int getResult() {
        return output;
    }
}

CalculationThread thread = new CalculationThread(1);
thread.start();
thread.join();
int result = thread.getResult();