列出通过删除项目获得线程安全

时间:2013-10-29 09:39:16

标签: multithreading list thread-safety

我正在尝试从列表中删除项目,直到多线程为空。

代码:

    public void testUsers() {
        final List<User> users = userDao.findAll();
        final int availableProcessors = Runtime.getRuntime().availableProcessors() * multiplier;
        final List<String> loggingList = Lists.newArrayList();
        final List<Integer> sizeChecked = Lists.newArrayList();
        int totalSizeChecked = 0;
        int sizeList = users.size();
        ExecutorService executorService = Executors.newFixedThreadPool(availableProcessors);
        for (int i = 0; i < availableProcessors; i++) {
            createThread(executorService, users, loggingList, sizeChecked);
        }

        executorService.shutdown();
        try {
        // wait for all threads to die
            executorService.awaitTermination(1, TimeUnit.HOURS);
        } catch (InterruptedException ex) {
        }

        for (Integer count : sizeChecked) {
           totalSizeChecked += count;
        }
        Assert.assertTrue(totalSizeChecked==sizeList);
   }

    private void createThread(ExecutorService executorService, final List<User> users,
        final Collection<String> loggingList, final List<Integer> sizeChecked) {

        executorService.execute(new Runnable() {
            @Override
            public void run() {
                int totalChecked = 0;
                while (!users.isEmpty()) {
                    User user = null;
                    synchronized (users) {
                        if (!users.isEmpty()) {
                            user = users.remove(0);
                        }
                    }
                    totalChecked++;
                    if (user != null) {
                        String reason = checkUser(user);
                        if (reason != null) {
                            loggingList.add(reason);
                        }
                    } else {
                        LOGGER.info("user is null");
                    }

                }
                sizeChecked.add(totalChecked);
            }
        });
    }

现在我认为这不会是错误的,因为我使列表同步以删除第一项。 我用6的乘数测试。(在prod上它将降低到1-2) 我在电子邮件中看到了这个: 批处理未正确执行。 必须检查的帐户大小:28499。已检查帐户的大小:25869

让它线程安全我有什么不对?

1 个答案:

答案 0 :(得分:1)

List<Integer> sizeChecked不是线程安全的。因此,您无法在其中并行添加元素。

同步add操作或使用线程安全的结构。如果sizeChecked只是一个计数器,请改用AtomicLong并使每个线程递增它。