我正在尝试从列表中删除项目,直到多线程为空。
代码:
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
让它线程安全我有什么不对?
答案 0 :(得分:1)
List<Integer> sizeChecked
不是线程安全的。因此,您无法在其中并行添加元素。
同步add
操作或使用线程安全的结构。如果sizeChecked
只是一个计数器,请改用AtomicLong
并使每个线程递增它。