Domanda

Sto cercando di scrivere un programma in Java utilizzando ExecutorService e la sua funzione invokeAll. La mia domanda è: non la funzione invokeAll risolvere i compiti contemporaneamente? Voglio dire, se ho due processori, ci saranno due operai allo stesso tempo? Perché aI non ce la fa scalare correttamente. Ci vuole lo stesso tempo per completare il problema se io do newFixedThreadPool(2) o 1.

List<Future<PartialSolution>> list = new ArrayList<Future<PartialSolution>>();
Collection<Callable<PartialSolution>> tasks = new ArrayList<Callable<PartialSolution>>();
for(PartialSolution ps : wp)
{
    tasks.add(new Map(ps, keyWords));
}
list = executor.invokeAll(tasks);

Map è una classe che implementa Callable e wp è un vettore di soluzioni parziali, una classe che contiene alcune informazioni in tempi diversi.

Perché non è vero scala? Quale potrebbe essere il problema?

Questo è il codice per PartialSolution:

import java.util.HashMap;
import java.util.Vector;

public class PartialSolution 
{
    public String fileName;//the name of a file
    public int b, e;//the index of begin and end of the fragment from the file
    public String info;//the fragment
    public HashMap<String, Word> hm;//here i retain the informations
    public HashMap<String, Vector<Word>> hmt;//this i use for the final reduce

    public PartialSolution(String name, int b, int e, String i, boolean ok)
    {
        this.fileName = name;
        this.b = b;
        this.e = e;
        this.info = i;
        hm = new HashMap<String, Word>();
        if(ok == true)
        {
            hmt = new HashMap<String, Vector<Word>>();
        }
        else
        {
             hmt = null;
        }    
    }
}

Un questo è il codice per la mappa:

public class Map implements Callable<PartialSolution>
{
    private PartialSolution ps;
    private Vector<String> keyWords;

    public Map(PartialSolution p, Vector<String> kw)
    {
        this.ps = p;
        this.keyWords = kw;
    }

    @Override
    public PartialSolution call() throws Exception 
    {
        String[] st = this.ps.info.split("\\n");
        for(int j = 0 ; j < st.length ; j++)
        {
            for(int i = 0 ; i < keyWords.size() ; i++)
            {
                if(keyWords.elementAt(i).charAt(0) != '\'')
                {
                    int k = 0;
                    int index = 0;
                    int count = 0;

                    while((index = st[j].indexOf(keyWords.elementAt(i), k)) != -1)
                    {
                        k = index + keyWords.elementAt(i).length();
                        count++;
                    }
                    if(count != 0)
                    {
                        Word wr = this.ps.hm.get(keyWords.elementAt(i));
                        if(wr != null)
                        {
                            Word nw = new Word(ps.fileName);
                            nw.nrap = wr.nrap + count;
                            nw.lines = wr.lines;
                            int grep = count;
                            while(grep > 0)
                            {
                                nw.lines.addElement(ps.b + j);
                                grep--;
                            }
                            this.ps.hm.put(keyWords.elementAt(i), nw);
                        }
                        else
                        {
                            Word nw = new Word(ps.fileName);
                            nw.nrap = count;
                            int grep = count;
                            while(grep > 0)
                            {
                                nw.lines.addElement(ps.b + j);
                                grep--;
                            }
                            this.ps.hm.put(keyWords.elementAt(i), nw);
                        }
                    }
                } 
                else
                {
                    String regex = keyWords.elementAt(i).substring(1, keyWords.elementAt(i).length() - 1);
                    StringBuffer sb = new StringBuffer(regex);
                    regex = sb.toString();
                    Pattern pt = Pattern.compile(regex);
                    Matcher m = pt.matcher(st[j]);
                    int count = 0;
                    while(m.find())
                    {
                        count++;
                    }
                    if(count != 0)
                    {
                        Word wr = this.ps.hm.get(keyWords.elementAt(i));
                        if(wr != null)
                        {
                            Word nw = new Word(this.ps.fileName);
                            nw.nrap = wr.nrap + count;
                            nw.lines = wr.lines;
                            int grep = count;
                            while(grep > 0)
                            {
                                nw.lines.addElement(ps.b + j);
                                grep--;
                            }
                            this.ps.hm.put(keyWords.elementAt(i), nw);
                        }
                        else
                        {
                            Word nw = new Word(this.ps.fileName);
                            nw.nrap = count;
                            int grep = count;
                            while(grep > 0)
                            {
                                nw.lines.addElement(ps.b + j);
                                grep--;
                            }
                            this.ps.hm.put(keyWords.elementAt(i), nw);
                        }
                    }
                }
            }
        }
        this.ps.info = null;
        return this.ps;
    }
}

Quindi, in Mappa prendo ogni linea dal frammento e la ricerca di ogni espressione del numero di presenze e salvare anche il numero della linea. Dopo che ho elaborare tutte le frammento, nella stessa PartialSolution i salvare le informazioni in una mappa di hash e torno il nuovo PartialSolution. Nella fase successiva combino i PartialSolutions con lo stesso nome e li presento in una classe Callable Ridurre, che è la stessa mappa, la differenza è che rende le altre operazioni, ma ritorna anche una PartialSolution.

Questo è il codice per eseguire i compiti mappa:

List<Future<PartialSolution>> list = new ArrayList<Future<PartialSolution>>();
Collection<Callable<PartialSolution>> tasks = new ArrayList<Callable<PartialSolution>>();
for(PartialSolution ps : wp)
{
   tasks.add(new Map(ps, keyWords));
}    
list = executor.invokeAll(tasks);

Nel compito genero compito di tipo Mappa e nell'elenco I ottenerli. Non so come leggere la discarica filo JVM. Spero che sia abbastanza buono quello che ti ho dato informazioni. Io lavoro in NetBeans 7.0.1 se funziona.

Grazie, Alex

È stato utile?

Soluzione

Quello che voglio sapere è se il metodo invokeAll, se ho creato l'ExcutorService con 10 thread, risolverà 10 compiti allo stesso tempo o risolverà una alla volta?

Se si invia compiti dieci a un ExecutorService con fili dieci, li eseguire tutti contemporaneamente. Se possono procedere completamente parallele e indipendenti l'uno dall'altro dipende da ciò che stanno facendo. Ma ciascuno di essi hanno il loro proprio thread.

E un'altra domanda, se io dico list.get (i) .get () questo restituirà il PartialSolution dopo che è stato risolto?

Sì, bloccherà fino a quando il calcolo è fatto (se non già fatto) e restituisce il suo risultato.

Io davvero non capisco perché non lo fa il tempo migliora se io uso 2 fili invece di 1.

Abbiamo bisogno di vedere più codice. Hanno sincronizzano su alcuni dati condivisi? Quanto tempo fanno queste operazioni prendono? Se sono molto brevi, non si può notare alcuna differenza. Se prendono più a lungo, sguardo alla discarica filo JVM per verificare che tutti loro sono in esecuzione.

Altri suggerimenti

Se si crea il pool di thread con due fili, quindi due compiti verrà eseguito allo stesso tempo.

ci sono due cose che vedo che potrebbe essere la causa di due thread per prendere la stessa quantità di tempo come un thread.

Se solo uno dei vostri compiti Mappa sta prendendo la maggior parte del tempo, allora le discussioni in più non farà che un compito correre più veloce. Non può finire più velocemente di quanto il lavoro più lento.

L'altra possibilità è che il vostro compito mappa legge da un vettore condiviso spesso. Ciò potrebbe causare abbastanza contesa per annullare il guadagno di avere due filetti.

Si dovrebbe portare questo fino a jvisualvm per vedere ciò che ogni thread sta facendo.

Java 8 ha introdotto un altro API Esecutori - newWorkStealingPool per creare lavoro rubare piscina. Non è necessario creare RecursiveTask e RecursiveAction ma ancora possibile utilizzare ForkJoinPool.

public static ExecutorService newWorkStealingPool()

Crea un pool di thread di lavoro furto utilizzando tutti i processori disponibili come suo livello obiettivo parallelismo.

Per impostazione predefinita, ci vorrà il numero di core della CPU, come parametro per il parallelismo. Se si dispone di core CPU, si può avere 8 thread per elaborare la coda compito di lavoro.

Work stealing of idle worker threads from busy worker threads improves overall performance. Since task queue is unbounded in nature, this ForkJoinPool is recommended for the tasks executing in short time intervals.

In entrambi i ExecutorService o ForkJoinPool o ThreadPoolExecutor prestazioni sarebbe bene se non si dispone di dati e di blocco condiviso (sincronizzazione) e la comunicazione tra filo comune. Se tutti i task sono indipendenti l'uno dall'altro nella coda compito, le prestazioni sarebbe migliorata.

ThreadPoolExecutor costruttore per personalizzare e controllare il flusso di lavoro dei compiti:

 ThreadPoolExecutor(int corePoolSize, 
                       int maximumPoolSize, 
                       long keepAliveTime, 
                       TimeUnit unit, 
                       BlockingQueue<Runnable> workQueue, 
                       ThreadFactory threadFactory,
                       RejectedExecutionHandler handler)

Date un'occhiata a domande SE correlati:

Come usare correttamente Java esecutore?

Java / Accedi vs ExecutorService - quando usare quale?

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