2013-03-18 29 views
2

我想要做的是修改一个线程内的全局ArrayList,并让这个修改的ArrayList在我的线程之外。我的意思是说,如果最后一个元素具有pollingCode,pollingType,轮询值= 0,那么这个元素有一个正确的大小,但这个ArrayList中的所有元素都是最后一个元素, 0,数组中的所有元素具有相同的值。从线程修改全局ArrayList

有谁知道为什么会发生这种情况?

public abstract class OverlayView extends RelativeLayout { 

protected ArrayList<InputEvent> eventList  = new ArrayList<InputEvent>(); 

public void StartEventMonitor() { 
     Thread b = new Thread(new Runnable() { 

       public void run() { 

        InputEvent ie= new InputEvent(); 
        while (m_bMonitorOn) { 
         for (InputDevice idev:events.m_Devs) { 
          // Open more devices to see their messages 

          int pollingEvent = idev.getPollingEvent(); 

           int pollingType=idev.getSuccessfulPollingType(); 
           int pollingCode=idev.getSuccessfulPollingCode(); 
           int pollingValue=idev.getSuccessfulPollingValue(); 

           final String line =/* idev.getName()+ 
             ": " +*/ idev.getSuccessfulPollingType()+ 
             " " + idev.getSuccessfulPollingCode() + 
             " " + idev.getSuccessfulPollingValue() + 
             "\n"; 
           Log.d(LT, "Event:"+line); 

           ie.setCode(pollingCode); 
           ie.setType(pollingType); 
           ie.setValue(pollingValue); 
           eventList.add(ie); 
          } 

         } 
        } 
       } 
      }); 
      b.start();  
    } 

}

回答

2

只是一个供参考此无关多线程。

您正在重新使用相同的InputEvent对象。所以你调用setCode你调用同一个InputEvent的setCode方法。添加只需每次添加相同的IE实例。

例如,尝试(假设列表大小> 1)

if(eventList.get(0) == eventList.get(1)){ 
    //re using the same object 
} 

你应该将InputEvent的创建任务里面的for循环。

+0

谢谢你。问题现在解决了;)我想这是我的错误,因为我总是试图避免新的对象创作,如果我不需要...通常当我添加元素到一个arrayList我通常使用相同的对象,只是改变值setter – 2013-03-18 15:32:06

+0

@CarlosMoreradeLaChica无论什么价值 - 一般形式的对象创建并不昂贵,你不应该担心。有一些像SimpleDateFormat和其他报道是昂贵的。 Josh Bloch指出,20%的CPU时间花费在80%的代码上。 – 2013-03-18 15:34:11

2

您是否尝试过创建的循环新InputEvent的。你只需要一个即您添加服务,您只需更新上InputEvent值:

InputEvent ie= new InputEvent(); 
while (m_bMonitorOn) { 
    ie= new InputEvent(); 
... 
2

没有研究你的代码的所有细节:你的列表不是线程安全的。我建议你使用类似ArrayBlockingQueue的东西来分享你的线程之间的事件。这将消除重大问题,无论如何都是正确的做法。

0

你有2个错误:

首先,改变:

protected ArrayList<InputEvent> eventList = new ArrayList<InputEvent>(); 

protected final List<InputEvent> eventList = 
    Collections.synchronizedList(new ArrayList<InputEvent>()); 

这将使增加,名单线程安全移除项目。现在我们需要解决添加项目的问题。对于每个事件,您都需要新的InputEvent实例。所以改变你的循环方式:

public void run() { 
    while (m_bMonitorOn) { 
     for (InputDevice idev:events.m_Devs) { 
      InputEvent ie= new InputEvent(); 
       ... 
      eventList.add(ie); 
     } 
    } 
} 
+0

非常感谢!但是我有疑问,这是使用 保护的ArrayList之间完全差 EVENTLIST =新的ArrayList (); 受保护的最终列表 eventList = 集合。synchronizedList(new ArrayList ()); 我不明白为什么这会使添加和删除列表线程安全的项目。 再次感谢 – 2013-03-18 16:05:54

+1

[final是线程安全发布的一种方式](http://www.javamex.com/tutorials/synchronization_final.shtml) – Leonidos 2013-03-18 23:13:30