【发布时间】:2015-03-17 18:44:21
【问题描述】:
这段代码有什么问题?
public class SimpleThreadPool {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 2000; i++) {
Runnable worker = new WorkerThread("" + i);
executor.execute(worker);
}
WorkerThread obj = new WorkerThread();
System.out.println(obj.getCount());
executor.shutdown();
while (!executor.isTerminated()) {
}
System.out.println("Finished all threads");
}
}
class WorkerThread implements Runnable {
private String command;
private volatile static int count;
public WorkerThread(){
}
public WorkerThread(String s){
this.command=s;
}
@Override
public void run() {
try {
synchronized (this) {
processCommand();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void processCommand() throws InterruptedException {
count++;
System.out.println("count " + count);
//Thread.sleep(500);
}
@Override
public String toString(){
return this.command;
}
public int getCount(){
return count;
}
}
我试图得到 count as 2000 的结果,最后也是如此......我的代码有什么问题??
如何确保计数始终以正确的顺序递增?
我什么时候应该使用 volatile 或 synchronized 块或两者兼而有之?
【问题讨论】:
-
您在循环中使用的是
2000,而不是20000。你还没有告诉我们你的代码有什么问题,执行的实际结果是什么以及它与你想要的有什么不同。 -
假设 processCommand() 应该做一些比增加计数器更重要的事情,那么在修复同步之后,原始设计仍然存在重大缺陷。 run() 中发生的第一件事是共享资源上的同步。在 Worker 应该完成的所有工作完成之前,不会释放该锁,这有效地消除了并行化带来的任何收益。 run 方法确实应该重新设计为同步、获取任何共享数据来执行此任务、发布、执行任务、同步、更新共享结果、发布。
-
那么有什么方法可以在不同步 processCommand() 的情况下实现最终输出为 2000
-
是的,正如我在上一条评论中提到的那样。您仅在访问共享资源的部分上进行同步。例如,如果 processCommand() 计算了一些应该添加到计数器的数字,则您仅在从计数器读取/写入时同步,因为这是线程之间共享的唯一数据集。如果您的最终结果确实是 int,您可以考虑查找 AtomicInteger
标签: java multithreading synchronized threadpoolexecutor