Il framework Fork-Join in Java è rotto?

3

Ho appena finito di leggere questo articolo che afferma che il framework Java Fork-Join non va bene per quasi tutte le attività realistiche. Sembra essere in gamba, ma non mi sento qualificato per dire se ha ragione o no. Per citare la conclusione:

The F/J framework is lacking as an API

  • It is deficient in “characteristics of a good API” (Joshua Bloch)

The F/J framework is severely inadequate as an application service

  • It is only available as an embedded server, no remote object access such as RMI
  • It is only recommended for aggregate data operations.
  • It is only recommended for users with very large data structures (humongous arrays)
  • It is only useful for machines with profuse processors (16+ recommended)
  • It is only useful for one request at a time
  • It is only useful for strictly limited processing (recommended)
    • must be plain (between 100 and 10,000 basic computational steps in the compute method)
    • compute intensive code only
    • no blocking
    • no I/O
    • no synchronization
  • It has no logging or alerting
  • It has no error/stall recovery
  • It has no ability to display/alter the current execution status
  • It relies on academic correctness rather than maintainability
  • It lacks scope
  • Its multi-tasking is faulty
  • It is inefficient
  • It cannot not scale to hundreds of processors
  • It is complex to the point of being incomprehensible
  • There is no user manual, just JavaDoc

The minuscule benefits of the F/J framework do not outweigh

  • the bloat this experiment adds to the Java™ run time for non fork-join users
  • the restrictions for developers looking to parallelize their software especially with JDK1.8

The F/J framework is an inadequate academic experiment underpinning a research paper, not a lightweight framework. It does not belong in the JDK.

Qualcuno può qui con una migliore comprensione di questo commento?

    
posta Johnny 03.03.2017 - 13:59
fonte

1 risposta

4

La risposta a questo messaggio è esaustiva: Qual è il framework fork / join migliore di un pool di thread? Qui troverai risposte di alto livello, scritte da esperti che sono molto bravi a spiegare i problemi che li circondano.

(Se qualcuno ha conoscenze a livello di esperti su questa domanda, ti preghiamo di contribuire invece a quel post di Overflow dello Stack, poiché altri esperti hanno già contribuito lì.)

(Non sono un esperto, quindi potrebbero esserci errori nella mia comprensione.)

Indicherò alcune delle sottili critiche là.

In primo luogo, la maggior parte degli articoli introduttivi su Fork / Join Parallelism utilizza erroneamente un esempio che è parallelo ai dati . Di fatto, la maggior parte delle volte, l'esempio utilizzato è parallelo imbarazzante . Esiste un gran numero di elementi di dati, con un calcolo identico da applicare a ciascuno di essi; tutti questi calcoli sono pronti per l'esecuzione; nessuno di questi calcoli comunica tra loro. Quando si ha un lavoro parallelo imbarazzante, non importa molto come lo si partiziona sui thread / core della CPU. Implementazioni semplici potrebbero superare le implementazioni avanzate; e considerando che la comunità Java riconosce la facilità di manutenzione del codice come una virtù, una semplice implementazione che soddisfi i requisiti (per tale lavoro imbarazzante parallelo) dovrebbe essere preferita.

Il furto del lavoro era un'altra caratteristica controversa. Non così nel mondo accademico - è considerato unanimemente una buona cosa. La qualità dell'implementazione è un'altra questione, però.

Parte del motivo per cui il framework fork / join attira tale critica è perché Java non usa un approccio che assomiglia al async/await di C #, che trasforma il codice sorgente di una singola funzione in una macchina a stati . La capacità di eseguire questa trasformazione è importante perché consente all'oggetto trasformato di uscire quando viene bloccato. Con "break out", ciò che intendo è restituire letteralmente dalla funzione call back al servizio executor, in modo che il servizio executor (thread) possa deselezionare ed eseguire un'altra attività ready-to-execute. Ciò richiede la confezione del codice rimanente che deve ancora essere eseguito in un'attività, ed è esattamente ciò che fa una "macchina a stati asincroni".

Quando il furto del lavoro è implementato in un ambiente che non trasforma il codice in macchine a stati asincroni, gli implementatori hanno deciso di consentire al thread che è stato bloccato di cercare ed eseguire altre attività che potrebbero trovare. Ci sono due pericoli. Innanzitutto, non vi è alcuna garanzia che "l'altro compito che potrebbe trovare" sia ben educato. Ad esempio, l'attività corrente potrebbe essere bloccata (in attesa) per un'altra attività che sarebbe terminata entro poche decine di millisecondi, mentre "l'altra attività che potrebbe trovare" potrebbe continuare a essere eseguita per un minuto. L'esecuzione di quell'altra attività nello stack di chiamate corrente significa che l'attività attualmente bloccata potrebbe non riprendere anche se le attività dipendenti sono terminate.

In un certo senso, merita qualche critica, ma le critiche che trovi nella pagina che hai collegato potrebbero aver messo fuori posto la causa principale di quelle carenze.

Vale la pena sottolineare che la "macchina di stato asincrona" C # è stata pubblicata diversi anni dopo Java 1.7.

    
risposta data 03.03.2017 - 19:21
fonte

Leggi altre domande sui tag