简体   繁体   English

如何从线程返回值(java)

[英]How to return value from thread (java)

I made a thread like this one bellow: 我做了这样的一个波纹管:

public class MyThread implements Runnable {
  private int temp;

  public MyThread(int temp){
     this.temp=temp;
  }

  @Override
  public void run() {
    temp+=10;
    return;
  }

  public int getTemp() {
    return temp;
  }
}

but when i try to use temp by getTemp i get 0 但是当我尝试通过getTemp使用temp时我得到0

class Main {
  MyThread foo = new MyThread(10);
  Thread a = new Thread(foo);
  a.start();
  int aa = foo.getTemp();       
  System.out.println(aa);
}

i just want to use the calculation i did in thread to be stored in some variables for later use. 我只想使用我在线程中所做的计算,将其存储在一些变量中以备后用。

Or simply add 或者只是添加

...
a.start();
a.join(); // Add this
...

to wait for the thread to finish before getting the result. 等待线程完成,然后再获得结果。

Your problem is that you're trying to get the result before it has been calculated. 您的问题是您试图在计算结果之前获得结果。 You should wait for the thread to finish before getting the result. 您应该等待线程完成后才能获得结果。 This answer is perhaps not the best but is the simplest. 这个答案也许不是最好的,但最简单。 As other people had already used the Executors class I didnt want to repeat their answers. 由于其他人已经使用过Executors课程,所以我不想重复他们的答案。 I would, however, familiarise yourself with Thread and its methods before moving onto Executors to help you get a better understanding of threads as, from your post, it appears you may be a novice in this area. 但是,在进入执行器以帮助您更好地理解线程之前,我会先熟悉Thread及其方法,因为从您的帖子看来,您似乎是该领域的新手。

Thanks to l4mpi (on the meta site) for pointing out the lack of explanation. 感谢l4mpi(在meta网站上)指出了缺乏解释的地方。

Use Callable instead of a Runnable , it will return a Future that you can use to retrieve the value once it is done. 使用Callable代替Runnable ,它将返回一个Future,一旦完成就可以用来检索该值。

You can use a named class instead of a lambda expression if you want to. 如果需要,可以使用命名类而不是lambda表达式

import java.util.concurrent.*;

public class ReturnValueFromThread {
    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<Object> foo = executor.submit(() -> {
            return doWork();
        });

        System.out.println("We will reach this line before doWork is done.");
        System.out.println(foo.get()); // Will wait until the value is complete
        executor.shutdown();
    }

    private static double doWork() throws Exception {
        Thread.sleep(2000);
        return Math.random();
    }
}

In this case, you have to use Callable instead of Runnable (very similar): http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Callable.html 在这种情况下,您必须使用Callable而不是Runnable(非常相似): http : //docs.oracle.com/javase/7/docs/api/java/util/concurrent/Callable.html

public class MyThread implements Callable<Integer> { 

    private int temp;

    public MyThread(int temp){
         this.temp=temp;
    }
    @Override
    public Integer call() {
        temp+=10;
        return temp;
    }

}


public static void main(String[] args) throws InterruptedException, ExecutionException {
           ExecutorService service =  Executors.newSingleThreadExecutor();
           MyThread myTask = new MyThread(10);
           Future<Integer> future = service.submit(myTask);
           Integer result = future.get();
           System.out.println(result);
}

You can try these code. 您可以尝试这些代码。 By using Future you can hold the value return when the thread end: 通过使用Future,您可以在线程结束时保留返回值:

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * @author mike
 * @date Sep 19, 2014
 * @description
 */
public class Calc {
    private static class MyCallable implements Callable<Integer> {
        private int temp = 0;

        public MyCallable(int temp) {
            this.temp = temp;
        }

        @Override
        public Integer call() {
            temp += 10;
            return temp;
        }
    }

    public static void main(String[] args) {
        MyCallable foo = new MyCallable(10);
        try {
            Future<Integer> result = Executors.newCachedThreadPool().submit(foo);
            System.out.println(result.get());
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
}

There are a few ways to "share" variables with Threads. 有几种与线程“共享”变量的方法。

The problem with your code is that you are passing an int which is passed by value . 代码的问题在于,您传递的是一个按值传递的int This means that temp and this.temp is not the same variable. 这意味着tempthis.temp是不同的变量。

Using a Future as other answers suggest is one way that you can share variables. 其他答案建议使用“ Future是共享变量的一种方法。 Using a Future , you can ensure that the Thread has finished before actually fetching the result of that Threads execution so might be more relevant to you. 使用Future ,可以确保在实际获取该线程执行的结果之前线程已完成,因此可能与您更相关。

Other ways of sharing variables among Threads that are Thread-safe, but does not guarantee that the Thread has finished execution: 在线程之间共享变量的其他方式是线程安全的,但不能保证线程已完成执行:

  • pass an AtomicInteger and use the set method to set value. 传递AtomicInteger并使用set方法设置值。
  • use a synchronized getter method that returns the Threads value. 使用返回Threads值的synchronized getter方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM