2

メインクラスで複数のスレッドを生成したエグゼキューターインターフェースを使用してマルチスレッドアプローチを実装しようとしています

class Main
{
    private static final int NTHREADS = 10;

    public static void main(String[] args)
    {
        .........
        String str = createThreads(document);
        .............
    }


    public String createThreads(String docString)
    {

        ........
        .......
        Map<String,String> iTextRecords = new LinkedHashMap<String, String>();
        if(!iText.matches(""))
        {
            String[] tokenizedItext = iText.split("\\^");
            ExecutorService executor = Executors.newFixedThreadPool(NTHREADS);
            for(int index = 0 ;index < tokenizedItext.length;index++)
            {
                Callable<Map<String,String>> worker = null;
                Future<Map<String,String>> map = null;
                if(tokenizedItext[index].matches("^[0-9.<>+-= ]+$") || tokenizedItext[index].matches("^\\s+$"))
                {
                    iTextRecords.put(tokenizedItext[index],tokenizedItext[index]);
                }
                else
                {
                    worker = new MultipleDatabaseCallable(tokenizedItext[index],language);
                    map = executor.submit(worker);
                    try
                    {
                        iTextRecords.putAll(map.get());
                    }
                    catch(InterruptedException ex)
                    {
                        ex.printStackTrace(System.out);
                    }
                    catch(ExecutionException ex)
                    {
                        ex.printStackTrace(System.out);
                    }
                }

            }

            executor.shutdown();
            // Wait until all threads are finish
            while (!executor.isTerminated())
            {

            }

    }
}

Callable クラスは次のとおりです。

class MultipleDatabaseCallable implements Callable<Map<String,String>> 
{
    @Override
    public Map<String, String> call() throws Exception {

        System.out.println("Entering: "+Thread.currentThread().getName());
        Map<String,String> map = new HashMap<String,String>();
        for(int i =0;i<50000;i++)
        {
            for(int i1 = 0 ;i1<5000;i1++)
            {
                for(int i2 =0;i2 <500;i2++)
                {

                }
            }
        }
        System.out.println("Exiting: "+Thread.currentThread().getName());
        return map;
    }
}

私が得ている出力は

Entering: pool-1-thread-1
Exiting: pool-1-thread-1
Entering: pool-1-thread-2
Exiting: pool-1-thread-2
Entering: pool-1-thread-3
Exiting: pool-1-thread-3
Entering: pool-1-thread-4
Exiting: pool-1-thread-4
Entering: pool-1-thread-5
Exiting: pool-1-thread-5
Entering: pool-1-thread-6
Exiting: pool-1-thread-6

出力を見ると、call メソッドで一度に 1 つのスレッドのみが入力され、他のスレッドは前のスレッドが存在する場合にのみ入力されるようです。ただし、複数のスレッドが call() メソッドに入って実行する必要があることが予想されます。また、NTHREADS = 1 にして同じプログラムを実行すると、NTHREADS = 10 の場合と同じ時間がかかります。

そのため、アプリケーションはシングル スレッド アプリケーションと同じように動作しているようです。実装で間違っていることを教えてください。

ありがとう

4

2 に答える 2

6

電話すると

                map = executor.submit(worker);

mapこの場合に返される値はFutureです。callable が値を返すまで、値を持たないことを意味します。今あなたが電話するとき

                    iTextRecords.putAll(map.get());

何が起こるかというと、現在のスレッドが ( 内でmap.get()) ブロックされ、callable が (他のスレッドで) 戻るのを待っています。

map.get()新しい呼び出し可能オブジェクトを送信する前に( per ) 呼び出し可能オブジェクトが終了するのを常に待機するため ( per ) executor.submit()、観察する順次実行を強制します。

タスクを並行して実行するには、最初に get を呼び出す前にすべてのタスクを開始する必要があります。たとえば、を作成してArrayList<Future<Map<String,String>>> futures = ...から行うことができます

  futures.add(executor.submit(worker)); 

タスクを送信し (map変数は必要ありません)、2 番目のループを作成します (ループの後にfor(int i ...)):

 for(Future<Map<String,String>> f: futures) {
     iTextRecords.putAll(f.get);
 }
于 2013-09-27T11:49:07.090 に答える
0

callable を提出している間に先物を収集する必要があります。送信が完了した後でのみ、先物で get() を呼び出します。

于 2013-09-27T12:18:21.713 に答える