Java--如何使用多執行緒對一個HashSet進行平行計算
阿新 • • 發佈:2018-12-11
這段時間工作比較忙。今天抽空整理了一個多執行緒使用場景。
當處理一個數據量比較大的集合時(每個元素的計算都耗時比較長)。由於只使用一個執行緒進行計算比較慢。所以想到多跑幾個執行緒進行處理。
1.每個執行緒可以自行計算要處理集合的開始和結束索引,確保每一個元素都被計算的到。
2.同時為了防止這個集合中資料的長度有變化,需要執行緒每一次計算前都重新獲取集合長度,重新計算該執行緒要計算這個集合的開始和結束索引。
3.執行緒數是通過xml配置來進行修改的。不用每次修改程式碼來改動執行緒數。
程式碼如下:
Main:(主函式的類)
/** * 使用可配置的多個執行緒來對一個大資料量的集合進行計算,每個執行緒計算其中的一部分資料。 執行緒每隔一段時間根據資料集合計算自身要計算的索引。然後再做計算。 * * @author Stalin 2018年9月21日上午9:51:04 */ public class Main { public static Set<String> set = new HashSet<>(); public static int count; public static void main(String[] args) { // 為set新增10w條資料 for (int i = 0; i < 100000; i++) { set.add("/home/test/dir" + i); } // 獲取執行緒總數量 count = getCount(); // 根據執行緒數建立足夠的執行緒 for (int i = 1; i <= count; i++) { Timer t = new Timer(i); t.start(); System.out.println("這是第" + i + "個執行緒,執行緒總數:" + count); } } // 獲取配置檔案中的執行緒數量 public static int getCount() { int count = 1; SAXReader reader = new SAXReader(); try { Document document = reader.read(new File("etc/config.xml")); Element root = document.getRootElement(); count = Integer.valueOf(root.element("Config").elementText("ThreadCount")); } catch (Exception e) { e.printStackTrace(); return count; } return count; } }
Timer(計算執行緒):
public class Timer extends Thread { private int startIndex; private int endIndex; private int index; public int getStartIndex() { return startIndex; } public void setStartIndex(int startIndex) { this.startIndex = startIndex; } public int getEndIndex() { return endIndex; } public void setEndIndex(int endIndex) { this.endIndex = endIndex; } public int getIndex() { return index; } public void setIndex(int index) { this.index = index; } public Timer(int index) {// 根據傳入的執行緒號,可以計算出開始索引和結束索引 this.index = index; } @Override public void run() { while (true) { List<String> timeList = new ArrayList<>(); // 將set的全部元素新增到list當中 timeList.addAll(Main.set); // 根據當前執行緒傳入的索引值計算要計算的開始索引和結束索引 if (timeList.size() != 0) { startIndex = 1 + (Main.set.size() / Main.count * (index - 1)); endIndex = 0 + (Main.set.size() / Main.count * index); if (index == Main.count) {// 最後一個執行緒,結束索引為set的最後一個下標。 endIndex = Main.set.size() - 1; } else if (index == 1) {// 第一個執行緒,開始索引應該為0, startIndex = 0; } System.out.println("這是第:" + index + "個計算執行緒,開始索引/結束索引:" + startIndex + "/" + endIndex); // 進行計算 int num = 0; for (int i = startIndex; i <= endIndex; i++) { if (timeList.get(i) != null) { num++; } } System.out.println("執行緒" + index + "計算了" + num + "個目錄"); } try { Thread.sleep(10000L); } catch (InterruptedException e) { e.printStackTrace(); } } } }
配置檔案如下:
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<Config>
<ThreadCount>5</ThreadCount>
</Config>
</Root>
執行結果如下:
由於我只是舉個例子,沒有在這裡一直更新set的值,有興趣的朋友可以自己嘗試一下。也是可以的哦~~
喜歡的朋友點個贊哦~~