2013-08-23 78 views
5

這個問題可能很容易回答,但我只是不明白。 我減少了我的問題,直到這段代碼被留下以便找到此問題的「原點」: 我試圖用循環填充線程的ArrayList。Java - 用循環填充線程ArrayList

public static int u=0; 

public void test(){ 
    while (u <10) { 
     synchronized(threadList){ 
      threadList.add(u, new Thread(){     
       @Override public void run(){      
        System.out.println("Thread at Index: " + u);      
       } 
      }); 
     } 
     u++;    
    } 

    threadList.get(2).start();  
} 

最後一行我想通過在索引'2'處啓動線程來測試上面的循環。 我在期待控制檯顯示「Thread at Index:2」,但是顯示如下: 「Thread at Index:10」 無論我在「.get(int)」方法中寫入哪個整數,I收到索引'10'。

這是爲什麼?以及如何解決這個問題?

線程的創建似乎正常工作...所以是整數'你'的問題?

我很感激任何幫助! 在此先感謝!

+8

'u'是靜態的,所以你總能獲得電流值('10'你的程序運行時)。您不保存在任何地方創建線程時使用的值。 –

+0

如果您的線程列表僅從一個線程(主線程?)訪問,則不需要使用它同步。 – Raedwald

回答

9

當您在run方法

@Override public void run(){      
    System.out.println("Thread at Index: " + u);      
} 

u當前值檢索到的基準u。在循環結束時和線程運行時,該值爲10

請嘗試以下

public static int u = 0; 

public void test(){ 
    while (u <10) { 
     synchronized(threadList){ 
      threadList.add(u, new Thread(){  
       int i = u; 

       @Override public void run(){      
        System.out.println("Thread at Index: " + i);      
       } 
      }); 
     } 
     u++;    
    } 

    threadList.get(2).start();  
} 

在您的匿名Thread類,你是一個實例字段i的值設置爲u時調用構造函數並執行run()當打印值了。

您在尚未執行的上下文中引用u,即線程。當run()方法最終被調用時,程序將評估變量u,但是在程序執行過程中,它的值將是10.如果相反,您執行上述操作,則變量i將保持該值那個確切的時刻。這是因爲當新的Thread開始並執行時,字段初始化發生並且u立即被評估。

+0

感謝您的快速回答。 是的,它的工作原理!謝謝! 但我真的不明白它爲什麼與「int i」一起工作。 ..是因爲int u是靜態的,並且在方法之外定義,並且int停留在方法內部,不能從外部訪問,因此它在循環運行時總是有一定的值。 對不起,我英語不好。 – SoundOfTheTuner

+0

對這樣的小Runnables稍作改進 - 爲了清晰和線程安全,使實例變量(在本例中爲i)「final」。 – user949300

+0

@music請參閱我的編輯答案 –

1
while (u <10) { 
     synchronized(threadList){ 

      final int u_final = u; 

      threadList.add(u, new Thread(){     
       @Override public void run(){      
        System.out.println("Thread at Index: " + u_final); 
       } 
      }); 
     } 
     u++;    
    } 

final變量,它清楚它的價值將是什麼,因爲它永遠不會改變。

+0

哦,我明白了......謝謝! 所以,如果我理解一切正確: 如果我使用了一個for循環,因爲它帶有一個循環變量(例如「int i = 0;」),它永遠留在這個循環中會更好嗎只在循環運行時更改其值? – SoundOfTheTuner

+0

@ MuSiCkiL88or您將不能直接在線程中使用for循環索引'i',因爲它屬於不同的範圍。試試吧,它不會編譯。 –

-1

有一個嘗試的兩種方法:

package com.test; 

import java.util.ArrayList; 

public class TestThread5 { 
    public static int u=0; 
    public ArrayList<Thread> threadList = new ArrayList<>(); 
    public void test() throws InterruptedException{ 
     while (u <10) { 
      synchronized(threadList){ 
       threadList.add(u, new Thread(){     
        @Override public void run(){      
         System.out.println("Thread at Index: " + u);      
        } 
       }); 
      } 
      u++;    
     } 
     for (u = 0; u < 10; u++) { 
      Thread thread = threadList.get(u); 
      thread.start(); 
      thread.join(); 
     } 
     // threadList.get(2).start();  
    } 
    public static void main(String[] args) throws InterruptedException { 
     new TestThread5().test(); 
    } 
} 

package com.test; 

import java.util.ArrayList; 
import java.util.Iterator; 

public class TestThread4 { 
    public int u=0; 
    public ArrayList<Thread> threadList = new ArrayList<>(); 
    public void test() throws InterruptedException{ 
     while (u <10) { 
      synchronized(threadList){ 
       threadList.add(u, new MyThread(u)); 
      } 
      u++;    
     } 
     for(Thread thread :threadList){ 
      thread.start(); 
      thread.join(); 
     } 
     // ((Thread) threadList.get(2)).start();  
    } 
    public static void main(String[] args) throws InterruptedException { 
     new TestThread4().test(); 
    } 
} 
class MyThread extends Thread{ 
    private int u; 
    public MyThread(int u){ 
     this.u = u; 
    } 
    @Override 
    public void run() { 
     System.out.println("Thread at Index: " + u); 
    } 

}