2

私がやろうとしているのは、スレッド内でグローバル ArrayList を変更し、この変更された ArrayList をスレッドの外に置くことです。

これは私のコードです。動作しますが、ArrayList を外部から読み取ると正しいサイズですが、この ArrayList のすべての要素が最後に追加されます。つまり、最後の要素に pollingCode、pollingType、polling Value = 0、すべての要素がある場合配列内の値は同じです。

なぜこれが起こるのか誰か知っていますか?

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();    
   }

}

4

4 に答える 4

2

参考までに、これはマルチスレッドとは何の関係もありません。

同じInputEventオブジェクトを再利用しています。したがって、呼び出すものsetCodeは、同じInputEventのsetCodeメソッドを呼び出すことです。追加するだけで、毎回同じIEインスタンスが追加されます。

たとえば、試してみてください(リストサイズが1より大きいと仮定)

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

InputEventの作成割り当てをforループ内に移動する必要があります。

于 2013-03-18T15:14:35.617 に答える
2

コードを詳細に調査せずに:リストはスレッドセーフではありません。ArrayBlockingQueueのようなものを使用して、スレッド間でイベントを共有することをお勧めします。それは主要な問題を取り除き、いずれにせよ正しいことです。

于 2013-03-18T15:15:04.713 に答える
2

ループで新しい InputEvent を作成しようとしましたか。つまり、リストを追加し、その値を更新するだけですInputEvent

InputEvent ie= new InputEvent();
while (m_bMonitorOn) {
    ie= new InputEvent();
 ...
于 2013-03-18T15:12:46.387 に答える
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);
        }
    }
}
于 2013-03-18T15:29:01.373 に答える