【问题标题】:submit method of Java concurrent frameworkJava并发框架的提交方法
【发布时间】:2016-06-01 19:26:44
【问题描述】:

Java并发框架的新提交方法。想知道当我调用提交或调用获取时线程是否被执行?研究了Oracle官方文档,但找不到太多信息。谢谢。

我指的是下面的示例,

http://www.vogella.com/tutorials/JavaConcurrency/article.html

package de.vogella.concurrency.callables;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class CallableFutures {
  private static final int NTHREDS = 10;

  public static void main(String[] args) {

    ExecutorService executor = Executors.newFixedThreadPool(NTHREDS);
    List<Future<Long>> list = new ArrayList<Future<Long>>();
    for (int i = 0; i < 20000; i++) {
      Callable<Long> worker = new MyCallable();
      Future<Long> submit = executor.submit(worker);
      list.add(submit);
    }
    long sum = 0;
    System.out.println(list.size());
    // now retrieve the result
    for (Future<Long> future : list) {
      try {
        sum += future.get();
      } catch (InterruptedException e) {
        e.printStackTrace();
      } catch (ExecutionException e) {
        e.printStackTrace();
      }
    }
    System.out.println(sum);
    executor.shutdown();
  }
} 

【问题讨论】:

  • @JBNizet,为回复投票,我阅读了这份文件。没有明确说明提交时是否执行任务(考虑简单的情况,有足够数量的活动线程,而不是要运行的任务数量)。我从文档中的猜测是,我提交时执行了任务,但我不确定,所以我才来这里问。感谢您的建议。
  • 如果有可用线程(即队列为空),则立即执行任务。否则,它会被放入队列中,直到有线程可用。
  • 任务在提交后执行,并且有空闲的工作线程来实际执行它。调用 get() 对执行没有影响。

标签: java multithreading java.util.concurrent


【解决方案1】:

不,调用提交不会执行任务。并且调用 get 不会执行任务。该任务在属于执行程序线程池的线程中异步处理。

调用提交方法给线程池一个任务。任务排队,直到池中的线程之一空闲。然后池将任务分配给调用代码的工作线程。

当您调用 Future.get 时,工作人员已完成处理您的任务,工作人员当前正在处理您的任务,或者任务仍在排队等待工作人员可用。如果你的任务完成了,那么future返回Callable任务返回的值,否则调用future的get方法会导致你的主线程阻塞,直到任务完成。

【讨论】:

  • 感谢内森,投赞成票。如果活动线程数多于任务数,我认为任务会在提交时执行(而不是在执行get方法时执行),对吗?
  • @LinMa:它仍然在排队,工人几乎没有时间开始处理任务。我认为认识到所涉及的分工仍然很有帮助,这就是为什么我回答说调用 submit 不会(直接)执行任务。
【解决方案2】:

submit() 方法将您的任务提交到线程池,而Future#get() 使当前线程等待,直到该任务已被池中的一个线程执行,无论它是否失败。

【讨论】:

  • 感谢 Nicolas,投赞成票。如果活动线程多于任务数,我认为任务会在提交时执行(而不是在执行get方法时执行),对吗?
  • 在你的情况下,如果所有线程都被使用并且队列已满,它将抛出异常
  • 如果没有可用线程且队列已满,想让当前线程执行任务,需要使用execute代替submit
  • 对不起,我理解错了,这种情况下会正常由pool管理,不认为是pool的问题
  • @LinMa, Re, “如果 ... [then] 我认为提交时任务将被执行...” 不要那样想。这是一种具体的思维方式。您应该考虑抽象。一个抽象的ExecutorService 将执行您提交的任务尽快get() 方法将等待(如果需要)任务完成,然后返回其值。抽象不会做出比这更多的承诺,如果这些承诺不足以满足您的需求,那么您使用了错误的抽象。
猜你喜欢
  • 1970-01-01
  • 2014-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多