2013-08-23 63 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); 
    } 

}