1

ExecutorServiceとその関数を使用して Java でプログラムを作成しようとしていますinvokeAll。私の質問は次のとおりinvokeAllです。関数はタスクを同時に解決しますか? つまり、プロセッサが 2 つある場合、同時に 2 つのワーカーが存在するということですか? 正しくスケーリングできないからです。newFixedThreadPool(2)または 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実装するクラスでCallableありwp、異なる時間にいくつかの情報を保持するクラスである Partial Solutions のベクトルです。

なぜスケールしないのですか?何が問題なのですか?

これは 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;
        }    
    }
}

これは Map のコードです。

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;
    }
}

したがって、マップでは、フラグメントからすべての行を取得し、出現回数ごとにすべての式を検索し、行数も保存します。すべてのフラグメントを処理した後、同じ PartialSolution で情報をハッシュ マップに保存し、新しい PartialSolution を返します。次のステップでは、PartialSolutions を同じ fileName と組み合わせて、Map と同じである Callable クラス Reduce に導入します。違いは、他の操作を行いますが、PartialSolution も返すことです。

これは、Map タスクを実行するためのコードです。

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 のタスクを作成し、リストではそれらを取得します。JVM スレッド ダンプの読み方がわかりません。私があなたに提供した情報で十分であることを願っています。それが助けになるなら、私は NetBeans 7.0.1 で働いています。

ありがとう、アレックス

4

3 に答える 3

2

私が知りたいのは、invokeAll メソッドが、10 個のスレッドで ExcutorService を作成した場合、同時に 10 個のタスクを解決するのか、それとも 1 つずつ解決するのかということです。

10 個のスレッドを持つ ExecutorService に 10 個のタスクを送信すると、それらすべてが同時に実行されます。それらが完全に並行して互いに独立して進行できるかどうかは、彼らが何をしているかにかかっています。しかし、彼らにはそれぞれ独自のスレッドがあります。

別の質問ですが、list.get(i).get() と言うと、解決後に PartialSolution が返されますか?

はい、計算が完了するまでブロックし (まだ完了していない場合)、その結果を返します。

1つではなく2つのスレッドを使用すると時間が改善されない理由が本当にわかりません.

もっとコードを見る必要があります。それらはいくつかの共有データで同期しますか? これらのタスクにはどのくらいの時間がかかりますか? それらが非常に短い場合、違いに気付かない場合があります。時間がかかる場合は、JVM スレッド ダンプを調べて、すべてが実行されていることを確認します。

于 2011-11-29T09:46:50.010 に答える
0

Java 8 では、Executors にもう 1 つの API が導入されました。それは、ワーク スティーリング プールを作成するためのnewWorkStealingPoolです。RecursiveTaskandを作成する必要はありませんがRecursiveAction、引き続き使用できますForkJoinPool

public static ExecutorService newWorkStealingPool()

使用可能なすべてのプロセッサをターゲット並列処理レベルとして使用して、ワークスティーリング スレッド プールを作成します。

デフォルトでは、並列処理のパラメーターとして CPU コアの数が使用されます。コア CPU がある場合、ワーク タスク キューを処理するために 8 つのスレッドを使用できます。

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.

ExecutorServiceまたは ForkJoinPoolまたは ThreadPoolExecutorのいずれかのパフォーマンスは、共有データと共有ロック (同期) およびスレッド間通信がない場合は良好です。すべてのタスクがタスク キュー内で互いに独立している場合、パフォーマンスが向上します。

ThreadPoolExecutorタスクのワークフローをカスタマイズおよび制御するためのコンストラクター:

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

関連する SE の質問をご覧ください。

Java Executor を適切に使用するには?

Java の Fork/Join と ExecutorService - いつどちらを使用するか?

于 2016-01-30T03:36:32.487 に答える
0

2 つのスレッドでスレッド プールを作成すると、2 つのタスクが同時に実行されます。

2 つのスレッドが 1 つのスレッドと同じ時間かかる原因となっている可能性があることが 2 つあります。

Map タスクの 1 つだけが時間の大半を占めている場合、余分なスレッドによってその 1 つのタスクの実行速度が向上することはありません。最も遅いジョブよりも速く終了することはできません。

もう 1 つの可能性は、map タスクが共有ベクトルから頻繁に読み取ることです。これにより、2 つのスレッドを持つことによる利点が相殺されるほどの競合が発生する可能性があります。

これを jvisualvm で表示して、各スレッドが何をしているかを確認する必要があります。

于 2011-11-29T22:07:15.093 に答える