【问题标题】:how to access List of lists concurrently如何同时访问列表列表
【发布时间】:2014-04-13 08:27:28
【问题描述】:

我有一个列表列表,我想做的是创建读取对象(列表)并将其从“sharedList”中删除的线程,如何使列表线程安全?我正在使用 synchronizedList ,但是如果一个线程被删除和对象而另一个线程正在读取另一个对象怎么办?因为 .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

【问题讨论】:

  • 我们不能在没有看到任何一行代码的情况下评论某些代码的线程安全性。邮政编码。
  • 您应该意识到的第一件事是 Hibernate 实体不是线程安全的,因此不应从多个线程访问。
  • 是的,没关系,假设现在只有 1 个线程用于休眠,我如何同时管理 sharedList 上的读/写操作?
  • Hibernate 不仅仅是一个线程,因为您将 Hibernate 实体存储在一个共享列表中。 sharedList 是同步的,因此它是线程安全的。不是它包含的列表。但不清楚您是否从多个线程访问它们。
  • 正在做的是......从数据库中获取页面,将它们存储在“小列表”中并将小列表存储在更大的列表中,线程正在为大列表读取

标签: java multithreading arraylist


【解决方案1】:

Collections.synchronizedList(new ArrayList()) 返回一个线程安全的集合包装器,其中对每个方法的访问都锁定在包装器实例上,这意味着只有一个线程可以调用此包装器上的任何方法。但是当你想迭代列表并执行一些可变操作时,你需要在包装对象上同步迭代这个列表,来自 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 的线程安全变体,其中所有可变操作(添加、设置等)都是通过创建底层数组的新副本来实现的。

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

【讨论】:

    猜你喜欢
    • 2014-03-27
    • 2018-09-05
    • 2014-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-05
    • 1970-01-01
    • 2020-04-21
    相关资源
    最近更新 更多