2016-12-01 93 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或任何其他包。只是线程,也许地图/ 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

可以通过paralledStream通过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()); 
}); 

如果您想了解如何通过自己编写多线程代码来实现的。这里是一个简单的示例:

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