Voglio inviare Runnable
attività in ForkJoinPool attraverso un metodo:Java ForkJoinPool con attività non ricorsive, funziona il furto del lavoro?
forkJoinPool.submit(Runnable task)
nota, io uso JDK 7.
Sotto il cofano, si trasformano in oggetti ForkJoinTask. So che ForkJoinPool è efficiente quando un'attività viene suddivisa in più piccole in modo ricorsivo.
Domanda:
funziona rubare ancora lavorano nel ForkJoinPool se non c'è ricorsione?
Ne vale la pena in questo caso?
Aggiornamento 1: Le attività sono piccole e possono essere sbilanciate. Anche per compiti strettamente uguali, cose come il cambio di contesto, la programmazione dei thread, il parcheggio, le mancate pagine ecc. Si mettono in mezzo allo squilibrio .
Aggiornamento 2: Doug Lea ha scritto nel gruppo Concurrency JSR-166 Interest, dando un suggerimento su questo:
Questo migliora notevolmente il throughput quando tutte le attività sono asincrone e sottoposti alla piscina piuttosto che biforcuta , che diventa un ragionevole metodo per strutturare le strutture degli attori, così come molti servizi semplici che è possibile utilizzare in alternativa a ThreadPoolExecutor per .
presumo, quando si tratta di ragionevolmente piccole attività della CPU-bound, ForkJoinPool è la strada da percorrere, grazie a questa ottimizzazione. Il punto principale è che questi compiti sono già piccoli e non richiedono una scomposizione ricorsiva. Il furto del lavoro funziona, indipendentemente dal fatto che si tratti di un'attività grande o piccola: le attività possono essere prese da un altro lavoratore libero dalla coda di un lavoratore occupato.
Update 3: Scalability of ForkJoinPool - analisi comparativa per Akka team di ping-pong mostra grandi risultati.
Nonostante ciò, per applicare ForkJoinPool in modo più efficiente è necessario ottimizzare le prestazioni.
Mi sono chiesto questo e penso che sia quello che hai menzionato con il parcheggio e il blocco dei fili. Questo è il motivo per cui ritengo che i buffer dell'anello (disruptor) siano persino più veloci di un fork fork non eseguito (almeno per le attività di evento non ricorsive). –
@Adam Gent Abbiamo usato anche Disruptor - È incredibilmente veloce. E sì, l'idea di RingBuffer è applicata in molte moderne strutture di dati. Tuttavia, differiscono nei casi d'uso: 1. un Disruptor utilizza 1 thread - 1 modello consumer per il pipelining e non può rubare il lavoro, mentre 2. FJ è un pool di worker - il lavoro è distribuito su un numero di thread (m: n). –
Ho familiarità con le differenze di fj - rb ma penso che entrambi potrebbero essere di benedizione di meno blocco, ma non sono un esperto in alcun modo. –