2016-12-01 7 views
2

別のスレッドが次のアイテムにアクセスしている間、各スレッドがforループの単一項目にアクセスしようとしています。私は、複数のスレッドを使用してこれを行いたいと、作成された複数のスレッドの数は、ユーザーによって入力されます。私はこれをexecutorserviceとストリームを使って行っています。私は単純なスレッドを使ってこれをやりたい以下は正しいですか?より良い方法がありますか?forループの各項目のマルチスレッド/並列化JAVA

Map<String, String> fileMap = new HashMap<>(); 
fileMap.put("Age", "Age is not remotely associated with it."); 
fileMap.put("Gender", "Gender plays a role but not that important."); 
fileMap.put("Money", "People do not believe but this is the only factor that matters."); 

Runnable myRunnable = new Runnable(){ 
    public void run(){ 
     for (Map.Entry<String, String> entry : fileMap.entrySet()) { 
      synchronized(this){ 
       int counter = 0; 
       Pattern p = Pattern.compile("not"); 
       Matcher m = p.matcher(entry.getValue()); 
       while (m.find()) { 
        counter++; 
       } 
       System.out.println("File Name: " + entry.getKey()); 
       System.out.println("Count: " + counter); 
       System.out.println(Thread.currentThread().getName()); 
      } 
     } 
    }  
}; 

int n = Integer.parseInt(args[0]); 
for (int x=0; x<n; x++) 
{ 
    Thread temp= new Thread(myRunnable, "Thread #" + x); 
    temp.start(); 
    System.out.println("Started Thread:" + x); 
} 

また、それは以前のスレッドがすでに値を計算しているので、バック前の項目に移動するにはいないのスレッドを持つことが可能でしょうか? ご協力いただければ幸いです。ありがとう

+0

はスレッドを持っていて、それが 'synchronized'のために実行をブロックしようとしているように見えます。この場合、「これ」は何ですか?既に見つかっている行を再処理しないようにしたい場合は、 'map'から削除してください。 –

+0

単純なスレッドの意味はわかりません。 Javaスレッドは、OpenCL/Cudaのようなインデックスを持っていませんので、実行可能なCOULDがインデックスを保持しているにもかかわらず、スレッドの機能を拡張する必要があります。作成しているスレッドの数が、処理している項目の数と必ずしも一致しないため、このアプリケーションのロジックにも欠陥があります。最小限私はあなたのforループを 'x

+0

@RalphRitoch私の英語を間違えます。私は '単純なスレッドを使ってこれを行う'ことを意味し、ExecutorServiceやその他のパッケージは使用しませんでした。おそらくMaps/ConcurrentHashMaps – Tao

答えて

1

ここにあなたの問題の解決策があります。これは、スレッド名を解析してインデックスを提供し、最後の配列を使用してスレッドにデータを渡す処理を行います。

Map<String, String> fileMap = new HashMap<>(); 
fileMap.put("Age", "Age is not remotely associated with it."); 
fileMap.put("Gender", "Gender plays a role but not that important."); 
fileMap.put("Money", "People do not believe but this is the only factor that matters."); 


final int[] tgSize = new int[]{0}; 
final Map.Entry[][] entryArr = new Map.Entry[1][]; 

Runnable myRunnable = new Runnable(){ 
    public void run(){ 
     Integer index = Integer.valueOf(Thread.currentThread().getName().substring(8)); 

     for(int i = index; i < fileMap.size(); i += tgSize[0]) { 
      int counter = 0; 
      @SuppressWarnings("unchecked") 
      Map.Entry<String, String> entry = entryArr[0][i]; 
      Pattern p = Pattern.compile("not"); 
      Matcher m = p.matcher(entry.getValue()); 
      while (m.find()) { 
       counter++; 
      } 
      synchronized(this) { 
       System.out.println("File Name: " + entry.getKey()); 
       System.out.println("Count: " + counter); 
       System.out.println(Thread.currentThread().getName());    
      } 
     } 
    }  
}; 

int n = Integer.parseInt(args[0]); 

tgSize[0] = n < fileMap.size() ? n : fileMap.size(); 
entryArr[0] = fileMap.entrySet().toArray(new Map.Entry[fileMap.size()]); 


for (int x=0; x<n && x < fileMap.size(); x++) 
{ 
    Thread temp= new Thread(myRunnable, "Thread #" + x); 
    temp.start(); 
    System.out.println("Started Thread:" + x); 
} 
+0

と一緒にスレッドしてくださいありがとう。これは完全に動作し、私が探していたものです。しかし、Map.Entry [] []を作成する必要がある理由を教えてください。 – Tao

+0

私はそれを得た。後で処理されるために配列に行くのは正しいですか? – Tao

+0

正しいです、それはGPU処理の仕組みの鏡です。最初に、グローバルメモリにデータを設定し、インデックスを使用してアイテムを処理して、シェーダーが同じ作業をしていないことを確認します。最終的な配列はjavaのグローバル(共有)メモリを模倣する良い方法です。 –

1

自分でマルチスレッドコードの書き方を学びたいのであればそれはAbacusUtil

final Pattern p = Pattern.compile("not"); 

Stream.of(fileMap).parallel(threadNum).map(entry -> { 
    Matcher m = p.matcher(entry.getValue()); 
    int count = 0; 
    while (m.find()) { 
     count++; 
    } 
    return Pair.of(entry.getKey(), count); 
}).forEach(entry -> { 
    N.println("File Name: " + entry.getKey() + ", Count: " + entry.getValue()); 
}); 

によってparalledStreamによって達成することができます。ここに簡単なサンプルがあります:

final int threadNum = 3; 
final ExecutorService executorService = Executors.newFixedThreadPool(threadNum); 
final Iterator<Entry<String, String>> iter = fileMap.entrySet().iterator(); 

for (int i = 0; i < threadNum; i++) { 
    executorService.execute(new Runnable() { 
     @Override 
     public void run() { 
      Entry<String, String> entry = null; 
      while (true) { 
       synchronized (iter) { 
        if (iter.hasNext() == false) { 
         break; 
        } 
        entry = iter.next(); 
       } 

       final Matcher m = p.matcher(entry.getValue()); 
       int count = 0; 
       while (m.find()) { 
        count++; 
       } 

       System.out.println("File Name: " + entry.getKey() + ", Count: " + count + ", thread: " + Thread.currentThread().getName()); 
      } 
     } 
    }); 
} 

宣言:私はAbacusUtilの開発者です。

+0

いいライブラリですが、彼は質問で "シンプルな"スレッドを使いたいと言っていました。彼はまた、彼が単純なことによって何を意味するのかを定義しなかった。 –

+0

あなたのライブラリーはmavenにありますか? –

+0

ねえ、あなたが言ったこのライブラリが本当に好きです! – GOXR3PLUS

0

問題を使用して、配列を反復処理する生のスレッドを使用してループを並列化する標準的な方法を以下に示します。

import java.util.*; 
import java.util.regex.*; 

public class MyClass { 

public static void main(String[] args) { 
    Map<String, String> fileMap = new HashMap<>(); 
    fileMap.put("Age", "Age is not remotely associated with it."); 
    fileMap.put("Gender", "Gender plays a role but not that important."); 
    fileMap.put("Money", "People do not believe but this is the only factor that matters."); 
    String[] keys = fileMap.keySet().toArray(new String[fileMap.size()]); 

    int n = 2; //Integer.parseInt(args[0]); 
    for (int x=0; x<n; x++) 
    { 
     Runnable myRunnable = new MyRunnable(fileMap, keys, x, n); 
     Thread temp= new Thread(myRunnable); 
     temp.start(); 
     //System.out.println("Started Thread:" + x); 
    } 
} 

    private static class MyRunnable implements Runnable { 
     private Map<String, String> fileMap; 
     private String[] keys; 
     private int threadID; 
     private int threadCount; 
     Pattern p = Pattern.compile("not"); 
     public MyRunnable(Map<String, String> fileMap, String[] keys, int threadID, int threadCount) { 
      this.fileMap = fileMap; 
      this.keys = keys; 
      this.threadID = threadID; 
      this.threadCount = threadCount; 
     } 
     public void run(){ 
      for (int i=threadID; i<keys.length; i+= threadCount) { 
       int counter = 0; 
       Matcher m = p.matcher(fileMap.get(keys[i])); 
       while (m.find()) { 
        counter++; 
       } 
       synchronized(MyClass.class){ 
        System.out.println("File Name: " + keys[i]); 
        System.out.println("Count: " + counter); 
        System.out.println("ThreadID: " + threadID); 
       } 
      } 
     }  
    } 
    } 
+0

ありがとう。私は別のクラスを作ることなくそれをやろうとしていました。しかし、その解決策は簡単です。ありがとうございました – Tao

関連する問題