java - 如何使用正确的 run() 方法实现来保持 CopyOnWriteArrayList 的线程安全?

标签 java multithreading concurrency executorservice

我正在使用 ExecutorServicefixedThreadPool。我通过实现 Runnable 接口(interface)来创建线程。在 run() 方法中,我调用一个耗时的函数(现在假设为 Thread.sleep()),最后将一个元素添加到线程安全 CopyOnWriteArrayList。我正在 for 循环中提交线程。在 for 循环结束时,我关闭 ExecutorService 并等待终止。

但是,列表中元素的数量与循环迭代的数量并不相同。我的并发思维错误在哪里?

以下是此问题的代码示例:

public class TestProgram {

    public static void main(String[] args) throws Exception {

        ExecutorService executor = Executors.newFixedThreadPool(4);
        CopyOnWriteArrayList<String> stringList = new CopyOnWriteArrayList<String>();

        for (int i = 0; i < 1000; i++) {
            executor.submit(new myThread(stringList));
        }

        executor.shutdown();
        executor.awaitTermination(10, TimeUnit.SECONDS);
        System.out.println(Integer.toString(stringList.size()));

    }
}

class myThread implements Runnable {

    CopyOnWriteArrayList<String> stringList;

    public myThread(CopyOnWriteArrayList<String> stringList) {
        this.stringList = stringList;
    }

    public void run() {
        String string = new String("test");

        try {
            Thread.sleep(100);
        } catch (InterruptedException ex) {
            Logger.getLogger(myThread.class.getName()).log(Level.SEVERE, null, ex);
        }
        stringList.add(string);

    }
}

最佳答案

您只是没有给它足够的时间来完成。如果您想串行执行此操作,则需要 1000 * 100 毫秒,即 100 秒。您正在使用四个线程运行它,因此除以 4 即可得到 25 秒。您只需等待 10 秒即可完成。为了安全起见,将其增加到 26 秒,您应该会看到结果。

ExecutorService#awaitTermination 将等待 N 秒来完成,如果没有完成,它将简单地返回并继续执行。为了证明我的观点,请检查返回值 System.out.println(executor.awaitTermination(10, TimeUnit.SECONDS));

这里更好的解决方案是使用new CountDownLatch(1000),将每个可运行任务添加到列表后countDown,最后让主线程等待完成。

关于java - 如何使用正确的 run() 方法实现来保持 CopyOnWriteArrayList 的线程安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27570122/

相关文章:

python - 如何在Python中同时启动线程

Java Lock支持内存一致性

java - 检查和控制实际并行运行的应用程序线程数

python - 多处理中 pool.join、pool.close 的目的?

concurrency - future 永远不会解决并兑现 promise

Java - 套接字在客户端断开连接之前不会读取?

java - 当数据包含不可显示的字符时,JAXB 输出无效的 XML

java - Java编译错误 “variable not found”持续存在

java - 将 Base64 编码的视频发布到服务器,OutOfMemoryError

c# - 用 C# 中的每个新线程打开一个新控制台?