如何正确使用线程池并从线程获取结果?

时间:2011-08-19 13:15:00

标签: java threadpool future

我很想尝试多线程编程(对我来说是新的)并且我有一些问题。

我正在使用带有TestTask的ThreadPoolTaskExecutor,它实现Runnablerun方法,可以睡眠X秒。一切顺利,所有的TestTask都在不同的线程中执行。好。 现在棘手的部分是我想知道在线程中进行的操作的结果。所以我在Google / stack / etc上阅读了一些内容,并尝试使用Future。而且它不再适用了:/

我使用get方法得到(哦真的吗?)call方法的结果,那部分正在运行,但TestTask是一个接一个地执行(而不是同时执行之前)。所以我猜我没理解到什么,但我不知道是什么......这就是我需要你帮助的原因!

发起测试的课程:

public void test(String test) {

    int max = 5;
    for (int i = 0; i < max; i++) {
        TestThreadService.launch(i);
    }
    System.out.println("END");

}

TestThreadService类:

public class TestThreadService {

private ThreadPoolTaskExecutor taskExecutor;

public void launch(int i) {
    System.out.println("ThreadNumber : "+i);
    taskExecutor.setWaitForTasksToCompleteOnShutdown(false);
    TestTask testTask = new TestTask(i);
    FutureTask<Integer> futureOne = new FutureTask<Integer>(testTask);
    taskExecutor.submit(futureOne);
    try {
        Integer result = futureOne.get();
        System.out.println("LAUNCH result : "+i+" - "+result);
    } catch (Exception e) {
        e.printStackTrace();
    }
  }

public void setTaskExecutor(ThreadPoolTaskExecutor taskExecutor) {
  this.taskExecutor = taskExecutor;
}

}

TestTask类:

public class TestTask implements Callable<Integer> {

public Integer threadNumber;
private Integer valeur;

  public TestTask(int i) {
    this.threadNumber = i;
  }

  public void setThreadNumber(Integer threadNumber) {
    this.threadNumber = threadNumber;
  }

    @Override
    public Integer call() throws Exception {
        System.out.println("Thread start " + threadNumber);
        // generate sleeping time
        Random r = new Random();
        valeur = 5000 + r.nextInt(15000 - 5000);
        System.out.println("Thread pause " + threadNumber + " " + valeur);
        try {
            Thread.sleep(valeur);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Thread stop" + threadNumber);
        return this.valeur;
    }

}

我在Java方面还不错,但这是我第一次尝试使用不同的线程,所以对我来说这是一个新的东西。

我做错了什么?

谢谢!

2 个答案:

答案 0 :(得分:1)

test方法中,

TestThreadService.launch(1);

应该是

TestThreadService.launch(i);

主要的是

Integer result = futureOne.get();

使用launch方法调用。在FutureTask上调用get()是一个阻塞操作,这意味着在任务完成之前它不会返回。这就是你看到串行行为的原因。您正在模拟的用例(种植一堆活动并等待它们完成)并不是ThreadPoolTask​​Executor非常适合的用例。它没有原始线程具有的“连接”功能。那个说法,你想要做的就是

public Future<Integer> launch(int i) {
    System.out.println("ThreadNumber : "+i);
    taskExecutor.setWaitForTasksToCompleteOnShutdown(false);
    TestTask testTask = new TestTask(i);
    FutureTask<Integer> futureOne = new FutureTask<Integer>(testTask);
    return taskExecutor.submit(futureOne);
  }

在你的测试方法中

public void test(String test) {
    List<Future<Integer>> tasks = new ArrayList<Future<Integer>>();
    int max = 5;
    for (int i = 0; i < max; i++) {
        tasks.add(TestThreadService.launch(i));
    }
    for (Future<Integer> task : tasks) {
        System.out.println("LAUNCH result : " + task.get());
    }
    System.out.println("END");

}

答案 1 :(得分:0)

你也可以将setWaitForTasksToCompleteOnShutdown(false)移动到另一个方法中,因为每次你启动一个线程都不会被调用,就像我看到的那样(不是很多线程),但在另一个场景中,有更多的任务:这是一项不必要且昂贵的工作。

您还可以在服务上创建一个公共方法,名为:configure();或者,pre-launch();在开始创建线程之前。

格鲁克!