如何同时访问列表列表

时间:2014-04-13 08:27:28

标签: java multithreading arraylist

我有一个列表列表,我想要做的是创建读取对象(列表)的线程并将其从“sharedList”中删除,如何使列表线程安全?我正在使用synchronizedList,但如果一个线程被移除并且另一个线程正在读取另一个对象时对象会怎么样? as .remove将对象移到左边....

填料类

public class DataFetcher implements Runnable {

    Session session = null;
    Criteria criteria = null;
    private List<Parts> partList = null;




    public DataFetcher() {

    }

    @Override
    public void run() {

        // while(true)
        List newPartList =getNParts(DBIndexGuard.getAllowedListSize());
        SharedList.addPartList(newPartList);


    }

    public List<Parts> getNParts(int listSize) {

        try {
            session = HibernateUtils.getSessionFactory().openSession();
            criteria = ....
            // *********** SYNCHRONIZATION OCCURS HERE ********************//
            criteria.setFirstResult(DBIndexGuard.getNextIndex());
            criteria.setMaxResults(listSize);
            partList = criteria.list();



        } catch (Exception e) {
            e.printStackTrace();

        } finally {

            session.close();
        }
        return partList;
    }

}

sharedList类

public class SharedList {

    private static final List<List<Parts>> sharedList = Collections.synchronizedList(new ArrayList());

    public List<List<Parts>> SharedList() {

        return sharedList;

    }

    static synchronized void addPartList(List partList) {
        sharedList.add(partList);
    }

    static synchronized List getPartList(int index) {

        return sharedList.get(index);
    }

    static synchronized void removePartList(int index) {
        sharedList.remove(index);
    }
}

工作线程

public class Finder implements Runnable {
    private List<Parts> partList = null;

    public Finder () {
    }

    @Override
    public void run() {

        operateOnList(partList);
    }

    public void operateOnList(List<Parts> partList) {
        for (Parts part : partList) {

        }

    }
}

我将创建多个查找器来处理sharedList

1 个答案:

答案 0 :(得分:2)

Collections.synchronizedList(new ArrayList())返回一个Thread-Safe包装集合,其中对每个方法的访问在包装器实例上被锁定,这意味着只有一个线程可以调用此包装器上的任何方法。但是当你想迭代列表并执行一些可变操作时,你需要在包装器对象上从这个列表同步迭代,来自javadoc:

It is imperative that the user manually synchronize on the returned list when iterating over it:

        List list = Collections.synchronizedList(new ArrayList());
                 ...
             synchronized (list) {
                 Iterator i = list.iterator(); // Must be in synchronized block
                 while (i.hasNext())
                     foo(i.next());
             }

Failure to follow this advice may result in non-deterministic behavior.

如果按顺序迭代列表至关重要,那么CopyOnWriteArrayList可能是一种方法。它允许你让多个线程迭代在同一个列表上,但我不确定这是否是你要找的,因为:

  

ArrayList的线程安全变体,其中通过创建基础数组的新副本来实现所有可变操作(添加,设置等)。

这意味着对列表的所有更改都不会对已经迭代的线程可见(除非列表不是您想要的,否则应该没问题)。从您的简短描述中我了解到您正在寻找一个包含一些对象的集合,并且您希望让多个线程访问此集合并一个接一个地轮询对象以进行某种处理。如果我的假设是正确的,那么你应该使用队列而不是列表来实现这种功能(例如BlockingQueue)。