2011-03-08 53 views
1

我在編寫一個非常簡單的程序,它創建了幾個線程來發送併發請求到一個特定的URL。我測量並存儲響應時間。我遇到的問題是,雖然我創建了我的響應時間數組作爲靜態和最終,我存儲在此數組中的值只存在於我的一個生成的線程內。只要我退出循環並進入主線程,數組就是空的(包含0個值)。所以我的代碼片段中的總和總是爲零。我意識到我的錯誤可能是一個非常基本的錯誤,但不幸的是我無法在網上找到類似的主題。你能否指點我正確的方向?謝謝。從不同線程填充數組

public class MyClass {  
static final long[] respTimes = new long[l]; 

public static void sendRequest() {...} 

public static void main(String[] args) throws Exception { 
    for(int i=0; i<l; i++) { 
     new Thread("" + i) { 
      public void run() { 
       long startTime = System.nanoTime(); 
       sendRequest(); 
       long estimatedTime = System.nanoTime() - startTime; 
       respTimes[i] = estimatedTime; 
      } 
     }.start(); 
    } 
     for(int i=0; i<l; i++) { sum += respTimes[i]; } 
} 

}

+0

除了我真的不認爲這個數組應該是最終的... – n00b 2011-03-08 21:21:03

+1

當我聲明變量'i'是非最終的時候,我不認爲'respTimes [i]'在匿名內部類中工作! – adarshr 2011-03-08 21:22:48

+0

@ n00b32 - 我看不出最後的數組中有什麼問題 – adarshr 2011-03-08 21:23:40

回答

7

這不是問題。你的問題是在你有機會產生結果之前打印結果。這樣做:

Thread [] theThreads = new Thread[10]; 

for (...) { 
    theThreads[i] = new Thread() { ... }.start(); 
} 

// now make sure all the threads are done 
for (...) { 
    // this waits for the thread to finish 
    theThreads[i].join(); 
} 

// now print things out 
+0

是真的,也沒有注意到^^ – n00b 2011-03-08 21:19:12

+0

iluxa,但爲什麼我能夠看到我生成的線程中的數組值?如果我試圖從循環內打印它們,至少其中一些出現。但是循環外部總是包含零。 – IgorM 2011-03-08 21:25:23

+0

假設每個請求需要1秒鐘。給定的線程將等待一秒鐘,然後愉快地打印出「請求花費1秒鐘」。主程序將花10毫秒啓動所有線程,打印時還沒有完成。 – iluxa 2011-03-08 21:27:33

0

:O static final array? O0是不能很好

嘗試通過構造函數傳遞數組的線程和主線程

http://en.wikipedia.org/wiki/Final_(Java)

最後一個變量只能分配一次創建它。

與常量的值不同,最終變量的值在編譯時不一定是已知的。

+0

請閱讀鏈接,即使你修復了你的問題 – n00b 2011-03-08 21:54:01

0

您可能正在經歷競賽狀況。 for循環在任何線程實際啓動和/或完成之前完成。

如果您使用的是JDK 1.5或更高版本,請使用java.lang.concurrent類進行研究。他們使這些類型的線程連接操作變得非常簡單。

HTH

+0

問題是,如果我直接從循環內打印數組值,我可以看到至少其中一些已經「在那裏」。 ))但是我的主線程中只能看到零。 – IgorM 2011-03-08 21:27:53

0

因爲我有一個臨牀厭惡靜態方法:P和組織代碼的事情(也注意到你沒有處理出來send方法中的任何例外)

public class MultiClient 
{ 
    private long[] responseTimes = null; 
    private Throwable[] errors = null; 
    public MultiClient(int count) 
    { 
    responseTimes = new long[count]; 
    errors = new Throwable[count]; 
    } 
    protected void sendRequestWrapper(int index) 
    { 
    long startTime = System.nanoTime(); 
    try 
    { 
     //original send request 
     sendRequest(); 
    } 
    // optionally you may put a catch() here to process errors 
    catch(Throwable t) 
    { 
     errors[index] = t; 
    } 
    finally 
    { 
     //this will guarantee response times filled up even in case of 
     //sendRequest raising an exception 
     responseTimes[index] = System.nanoTime() - startTime; 
    } 
    } 
    public void doStuff() 
    { 
    Thread[] threads = new Thread[count]; 
    //separete create thread calls 
    for(int i = 0; i < threads.length; i++) 
    { 
     threads[i] = new Worker(i); 
    } 
    //... from start calls 
    for(int i = 0; i < threads.length; i++) 
    { 
     threads[i].start(); 
    } 
    // wait till all threads are done 
    for(int i = 0; i < threads.length; i++) 
    { 
     threads[i].join(); 
    } 
    } 
    private class Worker extends Thread 
    { 
    private int index = -1; 
    public Worker(int index) 
    { 
     super("worker "+index); 
     this.index = index; 
    } 
    public void run() 
    { 
     MultiClient.this.sendRequestWrapper(index); 
    } 
    } 
    public long[] getResponseTimes(){ return responeTimes; } 
    public Throwable[] getErrors(){ return errors; } 
    public boolean sendFailed(int indeX){ return errors[index] != null; } 

    public static void main(String[] args) 
    { 
    int count = ...; // get count from somewhere (cmd line, hard coded etc.) 
    MultiClient multiClient = new MultiClient(count); //create an array filler 
    multiClient.doStuff(); //this will block till all the threads are done 
    long[] responseTimes = multiClient.getResponseTimes(); 

    //do whatever you want with the response times 
    } 

} 
+0

太棒了!非常感謝你。 – IgorM 2011-03-08 21:50:02