[英]Using Multiple Threads in Java To Shorten Program Time
我沒有太多制作多線程應用程序的經驗,但我覺得我的程序可能會受益於擁有多個線程。 我正在做一個更大規模的項目,涉及使用分類器(如機器學習)來分類大約32000個客戶。 我調試了程序,發現每個用戶需要大約一秒鍾的時間。 換句話說,這需要8.8小時才能完成!
有什么方法可以運行4個線程,每個線程處理8000個用戶? 第一個線程將處理1-8000,第二個線程為8001-16000,第三個線程為16001-23000,第四個為23001-32000。 此外,截至目前,每個分類都是通過從另一個類調用靜態函數來完成的...
然后,除了主要線程之外的其他線程應該結束。 這樣的事情可行嗎? 如果是這樣,如果有人可以提供有關如何執行此操作的提示或步驟,我將非常感激。 我熟悉關鍵部分(等待/信號)的想法,但對它沒什么經驗。
再次,非常感謝任何幫助! 歡迎提出如何處理這種情況的提示和建議! 不確定它是否重要,但我有一台處理器速度為2.53 GHZ的Core 2 Duo PC。
這對於Apache Hadoop來說太輕了,每個服務器需要大約64MB的數據塊......但是對於Akka Actors來說這是一個絕佳的機會,它恰好支持Java!
http://doc.akka.io/docs/akka/2.1.4/java/untyped-actors.html
基本上,你可以讓4個演員完成這項工作,當他們完成對一個用戶或可能更好的用戶進行分類時,他們要么將它傳遞給一個“接收者”演員,它將信息放入數據結構或文件中對於輸出,或者,您可以通過每次寫入文件來執行並發I / O ..然后可以在完成所有文件后檢查/組合文件。
如果你想獲得更多的花哨/強大,你可以把演員放在遠程服務器上。 與它們進行通信仍然非常容易,並且您將利用多個服務器的CPU /資源。
我自己寫了一篇關於Akka演員的文章,但它是在Scala中,所以我會饒你的。 但是如果你谷歌“akka演員”,你會得到很多關於如何使用它的手持實例。 勇敢,潛入並進行實驗。 “演員系統”是一個容易接受的概念。 我知道你可以做到這一點!
將數據拆分為實現Runnable的對象,然后將它們傳遞給新線程。
在這種情況下擁有四個以上的線程不會殺死你,但是你不能獲得比你擁有核心更多的並行工作(如評論中所述) - 如果線程多於核心,系統將不得不處理誰去了什么時候。
如果我有一個類客戶,並且我想發布一個線程來優先考慮8000個更大集合的客戶,我可能會這樣做:
public class CustomerClassifier implements Runnable {
private customer[] customers;
public CustomerClassifier(customer[] customers) {
this.customers = customers;
}
@Override
public void run() {
for (int i=0; i< customers.length; i++) {
classify(customer);//critical that this classify function does not
//attempt to modify a resource outside this class
//unless it handles locking, or is talking to a database
//or something that won't throw fits about resource locking
}
}
}
然后在其他地方發布這些線程
int jobSize = 8000;
customer[] customers = new customer[jobSize]();
int j = 0;
for (int i =0; i+j< fullCustomerArray.length; i++) {
if (i == jobSize-1) {
new Thread(new CustomerClassifier(customers)).start();//run will be invoked by thread
customers = new Customer[jobSize]();
j += i;
i = 0;
}
customers[i] = fullCustomerArray[i+j];
}
如果你的classify方法影響同一個資源,你必須實現鎖定,並且還會在某種程度上扼殺你獲得的優勢。
並發性非常復雜,需要經過深思熟慮,我還建議查看oracle docs http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html (我知道鏈接很糟糕,但希望oracle docs不會走動太多?)
免責聲明:我不是並發設計或多線程(不同主題)的專家。
如果將輸入數組拆分為4個相等的子陣列中的4個線程,則無法保證所有線程同時完成。 您最好將所有數據放在一個隊列中,讓所有工作線程從該公共隊列中提取。 使用安全的BlockingQueue實現,以便不寫低級同步/等待/通知代碼。
從java 6開始,我們有一些方便的並發工具。 您可能需要考慮使用線程池來實現更清晰的實現。
package com.threads;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ParalleliseArrayConsumption {
private int[] itemsToBeProcessed ;
public ParalleliseArrayConsumption(int size){
itemsToBeProcessed = new int[size];
}
/**
* @param args
*/
public static void main(String[] args) {
(new ParalleliseArrayConsumption(32)).processUsers(4);
}
public void processUsers(int numOfWorkerThreads){
ExecutorService threadPool = Executors.newFixedThreadPool(numOfWorkerThreads);
int chunk = itemsToBeProcessed.length/numOfWorkerThreads;
int start = 0;
List<Future> tasks = new ArrayList<Future>();
for(int i=0;i<numOfWorkerThreads;i++){
tasks.add(threadPool.submit(new WorkerThread(start, start+chunk)));
start = start+chunk;
}
// join all worker threads to main thread
for(Future f:tasks){
try {
f.get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
threadPool.shutdown();
while(!threadPool.isTerminated()){
}
}
private class WorkerThread implements Callable{
private int startIndex;
private int endIndex;
public WorkerThread(int startIndex, int endIndex){
this.startIndex = startIndex;
this.endIndex = endIndex;
}
@Override
public Object call() throws Exception {
for(int currentUserIndex = startIndex;currentUserIndex<endIndex;currentUserIndex++){
// process the user. Add your logic here
System.out.println(currentUserIndex+" is the user being processed in thread " +Thread.currentThread().getName());
}
return null;
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.