Domanda

Sto implementando un Quicksort parallelo come pratica di programmazione e, dopo aver finito, ho letto la pagina del tutorial Java sugli esecutori, che sembra che potrebbero rendere il mio codice ancora più veloce.Sfortunatamente, mi affidavo a join() per assicurarmi che il programma non continuasse finché tutto non fosse stato ordinato.In questo momento sto usando:

public static void quicksort(double[] a, int left, int right) {
    if (right <= left) return;
    int i = partition(a, left, right);

    // threads is an AtomicInteger I'm using to make sure I don't
    // spawn a billion threads.
    if(threads.get() < 5){

        // ThreadSort's run method just calls quicksort()
        Future leftThread = e.submit(new ThreadSort(a, left, i-1));
        Future rightThread = e.submit(new ThreadSort(a, i+1, right));

        threads.getAndAdd(2);
        try {
            leftThread.get();
            rightThread.get();
        }
        catch (InterruptedException ex) {}
        catch (ExecutionException ex) {}
    }
    else{
        quicksort(a, left, i-1);
        quicksort(a, i+1, right);
    }
}

Sembra funzionare bene, ma se eseguo e.shutdown() subito dopo aver chiamato il mio metodo quicksort() non ricorsivo, ha un sacco di RejectedExecutionExceptions, quindi presumo che non funzioni come avrei voluto.

Ad ogni modo, sto sostanzialmente cercando di ottenere la stessa funzionalità di leftThread.join() ma con un esecutore e la mia domanda è:

È questo il modo migliore per attendere che tutti i thread siano completati?

MODIFICARE:Ok, quindi ho capito perché ho ricevuto un sacco di errori dopo aver spento il mio Executor, era perché stavo chiamando questa funzione in un ciclo (per uniformare i tempi di esecuzione) e non creando un nuovo Executor.

È stato utile?

Soluzione

Che tipo di esecutore stai utilizzando?

ThreadPoolExecutor.awaitTermination() farà quello che stai chiedendo (è effettivamente un'operazione di join in blocco).

Per inciso, ThreadPoolExecutor ti consentirà di impostare limiti sul numero di thread, ecc...(potrebbe essere meglio che andare ricorsivo come quello che stai facendo se il numero di thread aumenta, non ne sono sicuro).

PS: dubito che gli esecutori renderanno il tuo codice più veloce, ma potrebbero renderlo più facile da leggere e mantenere.L'uso di un pool di thread renderà le cose più veloci per questo tipo di algoritmo e l'Executor semplifica il lavoro con i pool di thread.

Altri suggerimenti

Dare un'occhiata a Executors.newFixedThreadPool che ti consente di creare un pool di al massimo n thread (elimina il tuo "if") e il file ExecutorService.shutdown metodo e il ExecutorsService.awaitTermination metodo.

Potresti usare a Conteggio alla rovescia

PS - Dubito che gli esecutori rendano il tuo codice eseguito più velocemente, ma potrebbero rendere il tuo codice più facile da leggere e mantenere.L'uso di un pool di thread renderà le cose più veloci per questo tipo di algoritmo e l'esecutore rende facile lavorare con i pool di thread.

Questo non è corretto.

L'esecutore può essere "supportato" da un numero qualsiasi di sistemi di esecuzione diversi, inclusi i thread in pool.

È necessario chiamare correttamente la classe factory.

Inoltre è necessario decidere una politica per affrontare le situazioni in cui i lavori vengono inviati in coda più velocemente di quanto possano essere consumati, perché potresti non inizialmente esaurisci la memoria a causa dei limiti sull'esecuzione del thread, ma se metti in coda milioni di lavori, devono essere archiviati da qualche parte mentre attendono l'esecuzione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top