java - 在java中实现同步addAll到列表

标签 java collections thread-safety

Updated the question.. please check secodn part of question

我需要建立一个图书 ID 的主列表。我有多个线程任务,可以调出一部分书 ID。一旦每个任务执行完成,我就需要将它们添加到 book id 的 super 列表中。因此,我计划将下面的聚合器类实例传递给我的所有执行任务,并让它们调用 updateBookIds() 方法。为了确保线程安全,我将 addAll 代码保存在同步块(synchronized block)中。

任何人都可以建议这与同步列表相同吗?我可以只说 Collections.newSynchronizedList 并从所有线程任务中调用 addAll 到该列表吗?请澄清。

public class SynchronizedBookIdsAggregator {
    private List<String> bookIds;

    public SynchronizedBookIdsAggregator(){
        bookIds = new ArrayList<String>();
    }

    public void updateBookIds(List<String> ids){
        synchronized (this) {
            bookIds.addAll(ids);
        }
    }

    public List<String> getBookIds() {
        return bookIds;
    }

    public void setBookIds(List<String> bookIds) {
        this.bookIds = bookIds;
    }
}

谢谢, 哈里什

Second Approach

经过以下讨论,我目前正计划采用以下方法。如果我在这里做错了什么,请告诉我:-

public class BooksManager{
    private static Logger logger = LoggerFactory.getLogger();

    private List<String> fetchMasterListOfBookIds(){    
        List<String> masterBookIds = Collections.synchronizedList(new ArrayList<String>());
        List<String> libraryCodes = getAllLibraries();

        ExecutorService libraryBookIdsExecutor = Executors.newFixedThreadPool(BookManagerConstants.LIBRARY_BOOK_IDS_EXECUTOR_POOL_SIZE);
        for(String libraryCode : libraryCodes){
            LibraryBookIdsCollectionTask libraryTask = new LibraryBookIdsCollectionTask(libraryCode, masterBookIds);
            libraryBookIdsExecutor.execute(libraryTask);
        }
        libraryBookIdsExecutor.shutdown();

        //Now the fetching of master list is complete.
        //So I will just continue my processing of the master list

    }
}

public class LibraryBookIdsCollectionTask implements Runnable {
    private String libraryCode;
    private List<String> masterBookIds;

    public LibraryBookIdsCollectionTask(String libraryCode,List<String> masterBookIds){
        this.libraryCode = libraryCode;
        this.masterBookIds = masterBookIds;
    }

    public void run(){
        List<String> bookids = new ArrayList<String>();//TODO get this list from iconnect call
        synchronized (masterBookIds) {
            masterBookIds.addAll(bookids);
        }
    }
}

谢谢, 哈里什

最佳答案

Can I just say Collections.newSynchronizedList and call addAll to that list from all thread tasks?

如果您指的是 Collections.synchronizedList,那么是的,那可以正常工作。这将为您提供一个实现 List 接口(interface)的对象,其中来自该接口(interface)的所有方法都是同步的,包括 addAll

尽管如此,请考虑坚持使用现有的设计,因为它可以说是一种更简洁的设计。如果您将原始 List 传递给您的任务,那么它们就可以访问该接口(interface)上的所有方法,而它们真正需要知道的只是有一个 addAll 方法.使用您的 SynchronizedBookIdsAggregator 可以使您的任务与对 List 接口(interface)的设计依赖性分离,并消除它们调用 addAll 以外的东西的诱惑。

在这种情况下,我倾向于寻找某种类型的 Sink 接口(interface),但是当我需要它时似乎从来没有出现过...

关于java - 在java中实现同步addAll到列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9621998/

相关文章:

java - BoneCP:getConnection 方法是线程安全的还是我们必须处理它?

java - 无法应用插件 [id 'com.android.library']

java - 如何重命名 Java .class 文件?

java - 将上下文传递给多个线程是否安全?

java - 内容未添加到 pdf 页面

java - 如何使用computeIfAbsent()在HashMap中缓存数据?

java - 什么是不间断阻塞?

java - 如何停止有时间限制的进程

java - 嵌套循环的时间复杂度

c# - 设置 SortedDictionary 的第 i 个值