2016-02-24 12 views
5

Esiste una coda di attività in sospeso utilizzate in congiunzione con Java 8 Executors.newWorkStealingPool()?In Java 8, Executors.newWorkStealingPool() fornisce anche una coda di attività?

Ad esempio, supponiamo che il numero di nuclei disponibili sia 2 e che Executors.newWorkStealingPool() sia vuoto perché 2 attività sono già in esecuzione. Quindi cosa succede se un terzo compito viene inviato al responsabile del furto del lavoro? È in coda? E se lo è, quali sono i limiti se qualcuno su detta coda?

Grazie in anticipo.

+1

Non ho una risposta specifica e sono sorpreso che questo non sia documentato meglio. Ma almeno in OpenJDK 8, questo metodo produce un ['ForkJoinPool'] (https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinPool.html), che non usa semplicemente un 'BlockingQueue' come fanno altre implementazioni ... che causano molte controversie, portando a un sovraccarico. Le attività che non possono essere immediatamente eseguite * sono * comunque in coda. Questo è discusso (insieme ai limiti della coda) in un'altra risposta: http://stackoverflow.com/a/30045601/228171 –

risposta

4

Esiste una coda di attività in sospeso utilizzate in congiunzione con Java Executors.newWorkStealingPool()?

Sì, ogni thread è supportato con la propria deque. Quando un thread è terminato con le sue attività, esso prende l'incarico dalla deque dell'altro thread e lo esegue.

E se lo è, quali sono i limiti se presenti su detta coda?

Dimensione massima per le code è limitata dal numero: static final int MAXIMUM_QUEUE_CAPACITY = 1 << 26; // 64M

Quando la coda è piena viene generata un'eccezione incontrollato: RejectedExecutionException("Queue capacity exceeded")

3

Da grepcode di Executors e ForkJoinPool

Executors. newWorkStealingPool rendimenti ForkJoinPool

Esecutori:

public static ExecutorService newWorkStealingPool() { 
     return new ForkJoinPool 
      (Runtime.getRuntime().availableProcessors(), 
      ForkJoinPool.defaultForkJoinWorkerThreadFactory, 
      null, true); 
    } 

ForkJoinPool:

public ForkJoinPool(int parallelism, 
         ForkJoinWorkerThreadFactory factory, 
         UncaughtExceptionHandler handler, 
         boolean asyncMode) { 
     this(checkParallelism(parallelism), 
      checkFactory(factory), 
      handler, 
      asyncMode ? FIFO_QUEUE : LIFO_QUEUE, 
      "ForkJoinPool-" + nextPoolId() + "-worker-"); 
     checkPermission(); 
    } 

On execute():

public void execute(ForkJoinTask<?> task) { 
     if (task == null) 
      throw new NullPointerException(); 
     externalPush(task); 
    } 

externalPush chiama externalSubmit e puoi vedere i dettagli di WorkQueue in quella implementazione.

externalSubmit:

// Operazioni esterne

/** 
* Full version of externalPush, handling uncommon cases, as well 
* as performing secondary initialization upon the first 
* submission of the first task to the pool. It also detects 
* first submission by an external thread and creates a new shared 
* queue if the one at index if empty or contended. 
* 
* @param task the task. Caller must ensure non-null. 

*/ 

Potete trovare maggiori dettagli circa le dimensioni della coda in WorkQueue classe

static final class WorkQueue { 

documentazione su WokrQueue:

/** 
    * Queues supporting work-stealing as well as external task 
    * submission. See above for descriptions and algorithms. 
    * Performance on most platforms is very sensitive to placement of 
    * instances of both WorkQueues and their arrays -- we absolutely 
    * do not want multiple WorkQueue instances or multiple queue 
    * arrays sharing cache lines. The @Contended annotation alerts 
    * JVMs to try to keep instances apart. 
    */ 
    @sun.misc.Contended 

/** 
    * Capacity of work-stealing queue array upon initialization. 
    * Must be a power of two; at least 4, but should be larger to 
    * reduce or eliminate cacheline sharing among queues. 
    * Currently, it is much larger, as a partial workaround for 
    * the fact that JVMs often place arrays in locations that 
    * share GC bookkeeping (especially cardmarks) such that 
    * per-write accesses encounter serious memory contention. 
    */ 
    static final int INITIAL_QUEUE_CAPACITY = 1 << 13; 

    /** 
    * Maximum size for queue arrays. Must be a power of two less 
    * than or equal to 1 << (31 - width of array entry) to ensure 
    * lack of wraparound of index calculations, but defined to a 
    * value a bit less than this to help users trap runaway 
    * programs before saturating systems. 
    */ 
    static final int MAXIMUM_QUEUE_CAPACITY = 1 << 26; // 64M