【问题标题】:Synchronized objects removes from a reverse list [JList - SWING]同步对象从反向列表中删除 [JList - SWING]
【发布时间】:2016-11-04 23:40:14
【问题描述】:

我在使用自定义 AbstractListModel 管理 ArrayList 时遇到了麻烦。 这是我的模型:

TradesListModel.class

package window;

import java.util.ArrayList;

import javax.swing.AbstractListModel;

import main.Trade;

public class TradesListModel extends AbstractListModel<Object>{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private ArrayList<Trade> trades;

    public TradesListModel(){
        trades = new ArrayList<Trade>();
    }

    public void add(Trade trade){
        trades.add(0, trade);
        this.fireIntervalAdded(this, 0, 1);
    }

    public void remove(){
        trades.remove(trades.size()-1);
        this.fireIntervalRemoved(this, trades.size(), trades.size());
    }

    public void clear(){
        trades.clear();
        this.fireIntervalRemoved(this, 0, trades.size());
    }

    @Override
    public int getSize() {
        return trades.size();
    }

    @Override
    public Object getElementAt(int index) {
        return trades.get(index);
    }

}

如您所见,每个对象都由三个并发工作的线程添加到我的列表顶部。每个线程都通过调用我的主类中的方法来添加新对象:

public void addTrade(Trade trade){
            trades.add(trade);
            SwingUtilities.invokeLater(new Runnable(){

                @Override
                public void run() {
                    myModel.add(trade);
                }

            });
}

我还有另一个 newSingleThreadScheduledExecutor,它每 30 秒调用一次我的主类 remove() 的方法,以从我的自定义模型处理的列表中删除对象:

public boolean updateTrades(){
     Iterator<Trade> it = trades.iterator();
     try {
        synchronized(this){
            index = 0;
            while(it.hasNext()){
                Trade current = it.next();
                if(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()-current.getTime())>TIME){
                    it.remove();
                    SwingUtilities.invokeLater(new Runnable(){

                        @Override
                        public void run() {
                            lm.remove(index);
                        }
                    });
                }
                index++;
            }
        }
        return true;
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
     return false;
 }

trades 列表等于模型中的trades 列表。 我所做的是打印传递给模型的索引值,但它与主类的索引不对应,因为我多次收到此异常:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -6
at java.util.ArrayList.elementData(ArrayList.java:418)
at java.util.ArrayList.remove(ArrayList.java:495)
at window.TradesListModel.remove(TradesListModel.java:28)
at main.TradeFinder$2.run(TradeFinder.java:119)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

TradeFinder 是我的主要课程。

【问题讨论】:

    标签: java multithreading swing jlist


    【解决方案1】:

    让我们考虑以下示例:updateTrades 在列表中有三笔交易时被调用:[t0, t1, t2] 并且应将它们全部删除。

    在这种情况下,您将调用lm.remove 方法三次:使用索引012。在第一个之后,列表将包含[t1, t2],在第二个之后:[t2]。当你第三次调用它时,没有索引为2 的元素,所以你会得到IndexOutOfBoundsException

    要修复它,只需拨打 lm.remove(0) 三次。正如预期的那样,这将删除前三个元素。

    【讨论】:

    • 列表的第 i-th(从零开始)最后一个元素的索引为 size-i-1,因此您应该将 -1 添加到 trades.remove(trades.size()-index); 行。跨度>
    • 注意,fireIntervalAddedfireIntervalRemoved 的范围不一致。例如,您将元素添加到列表的开头,而fireIntervalAdded 报告该元素已添加到列表的末尾。这可能会导致错误的 UI 重绘。
    • 无论如何,updateTrades 方法仅由 scheduleExecutor 线程调用
    • 如何修复 fireIntervalAdded 和 fireIntervalRemoved?
    • this.fireIntervalAdded(this, 0, 1);this.fireIntervalRemoved(this, trades.size() - index, trades.size() - index);(请注意,该元素已在上一行中删除,因此不再需要 -1)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-03
    • 1970-01-01
    • 2020-04-17
    • 1970-01-01
    • 2021-02-11
    相关资源
    最近更新 更多