如何从线程返回值(java)

时间:2014-09-19 07:48:16

标签: java multithreading

我做了一个像这样的线程:

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;
  }
}

但是当我尝试通过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);
}

我只想使用我在线程中执行的计算存储在某些变量中供以后使用。

5 个答案:

答案 0 :(得分:3)

使用Callable代替Runnable,它会返回一个可用于在完成后检索值的Future。

如果您愿意,可以使用命名类而不是lambda expression

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();
    }
}

答案 1 :(得分:3)

或者只需添加

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

在获得结果之前等待线程完成。

您的问题是您在计算结果之前尝试获取结果。在获得结果之前,您应该等待线程完成。这个答案可能不是最好的,但却是最简单的。由于其他人已经使用过Executors类,我不想重复他们的答案。但是,在转到Executors之前,我会熟悉Thread及其方法,以帮助您更好地理解线程,因为从您的帖子中看来,您可能是这方面的新手。

感谢l4mpi (on the meta site)指出缺乏解释。

答案 2 :(得分:0)

在这种情况下,您必须使用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);
}

答案 3 :(得分:0)

您可以尝试这些代码。通过使用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();
        }
    }
}

答案 4 :(得分:0)

有几种方法可以与Threads“共享”变量。

您的代码存在的问题是您传递的intpassed by value。这意味着tempthis.temp不是同一个变量。

使用Future作为其他答案建议是一种可以共享变量的方法。使用Future,您可以确保在实际获取该Threads执行结果之前Thread已完成,因此可能与您更相关。

在线程安全的线程之间共享变量的其他方法,但不保证线程已完成执行:

  • 传递AtomicInteger并使用set方法设置值。
  • 使用返回Threads值的synchronized getter方法。