我正在使用ExecutorService
ExecutorService executor = Executors.newFixedThreadPool(20000);
我在ThreadSystem.java
类中有两个静态成员:
public static Integer count = 0;
public static Integer rejectedCount = 0;
然后在其中添加线程:
for (i = 0; i < 20001; i++) {
Runnable worker = new MyThread();
try {
executor.execute(worker);
} catch (RejectedExecutionException ex) {
rejectedCount++;
}
}
executor.shutdown();
while (!executor.isTerminated()) {
}
在线程内:
@Override
public void run() {
ThreadSystem.count++;
try{
Thread.sleep(50);
}
catch(InterruptedException ex){
Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, ex.getMessage(),ex);
}
}
我得到的结果表明有些线程没有执行,count
变量不等于创建的线程数,尽管引用拒绝线程的rejectedCount
是0:
数:19488
拒绝数:0
那么还有什么可以保证我所有线程都可以运行的?那是什么原因:计数(可运行线程)不等于添加的线程?
答案 0 :(得分:6)
您的代码是竞争条件的“完美范例”:您对
的访问 public static Integer count = 0;
未同步,因此多个线程可能同时执行以下行:
ThreadSystem.count++;
这可能/可能导致写入丢失,因为多个线程可能同时执行与ThreadSystem.count = ThreadSystem.count + 1
等效的操作,并且某些线程会读取该操作的旧的尚未更新的数字。
要么使用适当的synchronized
防护罩,要么使用AtomicInteger#incrementAndGet()
周围的东西作为计数器。
请注意,在这种情况下,您不得在count
上进行同步,因为Integer
是不可变的对象,并且对装箱的基元(int
Integer
,long
至Long
,...)基本上是对该变量的赋值。使用AtomicInteger
是解决此特定问题的最佳解决方案。
您的(不正确,因为它仅由一个线程更新。)rejectedCount
也是如此。