Java 这是在多线程中计数的正确方法吗?
我想在5个线程完成后从WorkerThread类获取所有计数。计数器是否按预期的方式工作?谢谢在WorkerThread构造函数中,似乎每个计数器成为每个线程的一个变量,而不是在5个线程之间共享Java 这是在多线程中计数的正确方法吗?,java,multithreading,Java,Multithreading,我想在5个线程完成后从WorkerThread类获取所有计数。计数器是否按预期的方式工作?谢谢在WorkerThread构造函数中,似乎每个计数器成为每个线程的一个变量,而不是在5个线程之间共享 public class Test { public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(5); Counter co
public class Test {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);
Counter counter = new Counter();
for (int i = 0; i < 10; i++) {
Runnable worker = new WorkerThread(String.valueOf(i), counter);
executor.execute(worker);
}
executor.shutdown();
System.out.println("Total Count: " + counter.value());
while (!executor.isTerminated()) {
}
System.out.println("Finished all threads");
}
}
class Counter{
private AtomicInteger count;
public Counter(){
count = new AtomicInteger();
}
public int increment(){
return count.incrementAndGet();
}
public int value(){
return count.get();
}
}
class WorkerThread implements Runnable {
private String command;
private Counter c;
public WorkerThread(String s, Counter c){
this.command=s;
this.c = c;
}
@Override
public void run() {
for(int i=0; i<6; i++){
c.increment();
}
processCommand();
}
private void processCommand() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public String toString(){
return this.command;
}
}
公共类测试{
公共静态void main(字符串[]args){
ExecutorService executor=Executors.newFixedThreadPool(5);
计数器=新计数器();
对于(int i=0;i<10;i++){
Runnable worker=new WorkerThread(String.valueOf(i),计数器);
执行人,执行人(工人);
}
executor.shutdown();
System.out.println(“总计数:+counter.value());
而(!executor.isTerminated()){
}
System.out.println(“完成所有线程”);
}
}
班级计数器{
私有原子整数计数;
公众柜位(){
count=新的原子整数();
}
公共整数增量(){
返回count.incrementAndGet();
}
公共int值(){
返回count.get();
}
}
类WorkerThread实现Runnable{
私有字符串命令;
私人柜台c;
公共WorkerThread(字符串s,计数器c){
this.command=s;
这个.c=c;
}
@凌驾
公开募捐{
对于(int i=0;i同步对我来说似乎是正确的。如果计数是您唯一的任务,您可以跳过计数器类,直接使用AtomicInteger来消除复杂性。(如果您想要实现更复杂的任务,需要适当的同步共享状态对象,请保留它)
不要称你的工人类为“线程”。它不是一个线程,而是一个由线程执行的任务
最后但并非最不重要的一点是,您的关机代码有问题。请注意,关机不会阻塞,而是立即返回。因此,您对计数器的评估太早了
以下代码修复了所有这些问题:
public class Test {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);
AtomicInteger counter = new AtomicInteger();
for (int i = 0; i < 10; i++) {
executor.execute(new Worker(counter));
}
executor.shutdown();
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
// executor does not shut down.
// try executor.shutdownNow() etc.
}
System.out.println("Total Count: " + counter.get());
}
}
class Worker implements Runnable {
private final AtomicInteger counter;
public Worker(AtomicInteger counter) {
this.counter = counter;
}
public void run() {
// do something
counter.incrementAndGet();
// do something else
}
}
公共类测试{
公共静态void main(字符串[]args){
ExecutorService executor=Executors.newFixedThreadPool(5);
AtomicInteger计数器=新的AtomicInteger();
对于(int i=0;i<10;i++){
执行人。执行人(新工人(柜台));
}
executor.shutdown();
如果(!执行器等待终止(60,时间单位秒)){
//执行器不会关闭。
//尝试executor.shutdownNow()等。
}
System.out.println(“总计数:+counter.get());
}
}
类工作者实现可运行的{
专用最终原子整数计数器;
公共工作者(原子整数计数器){
this.counter=计数器;
}
公开募捐{
//做点什么
counter.incrementAndGet();
//做点别的
}
}
有关如何正确关闭ExecutorService
的更多信息,请参阅“使用示例”一节。我不理解这个问题。问题是什么?您不应该e.printStackTrace()
一个InterruptionException
。至少应该Thread.currentThread().interrupt()
。此外,为了便于阅读,您可以使用时间单位。秒。睡眠(5L);
。您可能想浏览一下本教程;它将让您了解这个.c=c
实际上在做什么。的javadoc表示它不会等待线程终止。我多次运行该程序,结果似乎并不总是正确的。有时是30,有时是24。在切换时应该始终是30g直接使用AtomicInteger
可以简化此特定示例中的代码,我绝对不建议将其作为一般方法。使用计数器
类可以添加其他功能,例如值更改时的回调和进度通知,以及等待计数器达到特定值的能力值(以及根据需求切换到其他实现的能力,例如信号量
或倒计时闩锁
等).aAtomicInteger
本身并没有太多功能。我同意。但在那个特定的示例中,计数器类使代码更加复杂,并分散了对同步主要问题的注意力。不过,我会更新我的答案。