Java 从其他线程更新AtomicInteger
我有一个类,它在各自的线程上创建了许多新对象,我希望保持线程间的运行计数。我想要一个Java 从其他线程更新AtomicInteger,java,multithreading,atomicinteger,Java,Multithreading,Atomicinteger,我有一个类,它在各自的线程上创建了许多新对象,我希望保持线程间的运行计数。我想要一个AtomicInteger,但它没有达到我的预期,而是得到了一个更小的版本。我假设这是一个竞赛条件错误,但我不能完全确定 A创建了这个测试示例,它重新创建了我想要做的事情 public class Test { public static void main(String args[]) { AtomicInteger total = new AtomicInteger(0);
AtomicInteger
,但它没有达到我的预期,而是得到了一个更小的版本。我假设这是一个竞赛条件错误,但我不能完全确定
A创建了这个测试示例,它重新创建了我想要做的事情
public class Test {
public static void main(String args[]) {
AtomicInteger total = new AtomicInteger(0);
for (int i = 0; i < 10; i++) {
DoThing doThing = new DoThing();
Thread thread = new Thread(doThing);
thread.start();
total.addAndGet(doThing.getTally());
}
System.out.println(total.get());
}
}
class DoThing implements Runnable {
int tally = 0;
@Override
public void run() {
for(int i = 0; i< 100; i++) {
tally++;
}
System.out.println("Tally is " + tally);
}
public int getTally() {
return tally;
}
}
当我希望最终输出为1000时。如何跨线程递增
提前感谢。是的,有一场数据竞赛。争用是在调用
doThing.gettaly()
的主线程和启动的“worker”线程之间进行的。看起来每次主线程都能够可靠地从每个工作线程获得“计数”,而工作线程甚至还没有机会进入其for
循环。甚至在worker调用其run()
方法之前就可能发生这种情况
您的主线程需要加入工作线程:
- 创建并启动十个工作线程,并将每个工作线程添加到
列表中
- 然后在一个单独的循环中,为列表中的每个线程调用
。t.join()
函数等待线程t.join()
完成其工作t
- 最后,把这些数字加起来李>
在主线程中打印原子值之前,必须等待所有线程完成。
如果您想使用低级阻塞,可以使用CyclicBarrier使主线程等待所有线程
CountDownLatch闩锁=新的CountDownLatch(10);
CountDownLatch latch = new CountDownLatch(10);
List<DoThing> things = new ArrayList();
AtomicInteger total = new AtomicInteger(0);
for (int i = 0; i < 10; i++) {
DoThing doThing = new DoThing(latch);
things.add(doThing);
Thread thread = new Thread(doThing);
thread.start();
total.addAndGet(doThing.getTally());
}
// Wait till all the threads are done.
// Each thread counts the latch down
latch.await()
int total = 0;
// Calculate sum after all the threads are done.
for (DoThing thing: things) {
total += thing.getTally();
}
System.out.println(total);
class DoThing implements Runnable {
private CountDownLatch latch;
public DoThing(CountDownLatch latch) {
this.latch = latch;
}
int tally = 0;
@Override
public void run() {
for(int i = 0; i< 100; i++) {
tally++;
}
latch.countDown();
System.out.println("Tally is " + tally);
}
public int getTally() {
return tally;
}
}
List things=new ArrayList();
AtomicInteger总计=新的AtomicInteger(0);
对于(int i=0;i<10;i++){
DoThing DoThing=新的DoThing(闩锁);
添加(点滴);
螺纹=新螺纹(圆点);
thread.start();
total.addAndGet(doThing.gettaly());
}
//等待所有线程完成。
//每个线程都会对闩锁进行计数
等待
int-total=0;
//完成所有线程后计算总和。
为了(溺爱的事物:事物){
total+=thing.gettaly();
}
系统输出打印项次(总计);
类DoThing实现可运行{
私人倒计时闩锁;
公共点滴(倒计时闩锁){
this.latch=闩锁;
}
整数=0;
@凌驾
公开募捐{
对于(int i=0;i<100;i++){
理货++;
}
倒计时();
System.out.println(“理货是”+理货);
}
公共int gettaly(){
返回理货;
}
}
试试这个:
public static void main(String args[]) {
AtomicInteger tally = new AtomicInteger(0);
List<Thread> threadList = new ArrayList<Thread>();
for (int i = 0; i < 10; i++) {
Thread t = new Thread(new DoThing(tally));
t.start();
threadList.add(t);
}
for (Thread t : threadList) {
try { t.join(); } catch (Exception e){}
}
System.out.println("Total tally: " + tally.get());
}
public static class DoThing implements Runnable {
private static final Random rand = new Random();
private final AtomicInteger tally;
public DoThing(AtomicInteger tally) {
this.tally = tally;
}
@Override public void run() {
for (int i = 0; i < 100; i++) {
int currTally = tally.incrementAndGet();
System.out.println("Thread " + Thread.currentThread().getName() + ": " + currTally);
// Random sleep to show that your threads are properly concurrently incrementing
try { Thread.sleep(rand.nextInt(10)); } catch (Exception e) {}
}
}
}
publicstaticvoidmain(字符串参数[]){
AtomicInteger Tall=新的AtomicInteger(0);
List threadList=new ArrayList();
对于(int i=0;i<10;i++){
螺纹t=新螺纹(新圆点(计数));
t、 start();
添加(t);
}
对于(线程t:线程列表){
尝试{t.join();}捕获(异常e){}
}
System.out.println(“总计数:+tally.get());
}
公共静态类DoThing实现可运行{
私有静态最终随机兰德=新随机();
私人最终原子计数;
公共点滴(原子整数){
this.tally=理货;
}
@重写公共无效运行(){
对于(int i=0;i<100;i++){
int currTally=tally.incrementAndGet();
System.out.println(“线程”+Thread.currentThread().getName()+”:“+currTally”);
//随机睡眠以显示线程正确地同时递增
尝试{Thread.sleep(rand.nextInt(10));}catch(异常e){}
}
}
}
问题的根源在于您误解了如何使用AtomicInteger
,您将其视为正常的int
,并且根本无法同时访问它
另外,在通过调用thread.join()
确保线程已完成之前,gettaly()
也是一个争用条件
因此,您可以通过让线程中的所有
Runnable
s更新相同的AtomicInteger
实例来保持最新的计数,并且您可以通过等待所有线程通过join()完成计数来确保总数正确
join只需按顺序运行所有线程,即可终止所有多线程处理。join将根据您的操作方式终止所有多线程处理。@ekaerovets。您可以创建一个线程数组,启动所有线程,然后遍历该数组并在每个线程上调用jointhread@ekaerovets,没有,因为我建议使用两个循环。一个用于启动线程,将每个线程保存在一个列表中,然后第二个循环将它们全部连接起来。@Ivan是的,这是有意义的。我没有考虑过。这会起作用,但它忽略了关于如何使用AtomicInteger
的误解。您需要等到线程完成任务后再调用doThings.gettaly()
如果你解释一下,而不是仅仅为他(或她)做那家伙(或杜德特)的家庭作业,这将是一个更好的答案。@jameslarge,也许吧。我认为这个例子是不言自明的,我个人更喜欢几行代码而不是解释。不过,如果这是一个家庭作业,你是对的。非常感谢!这不是家庭作业。只是在做点什么。这非常有用。它不会打印0吗?在请求最终结果之前,您不需要等待所有已启动的线程完成吗?抱歉,打印总计数是一个剩余值。是的,您应该连接所有线程以获得最终结果,但在本例中,这并不重要,因为每个线程每次递增计数时都会打印。我已经添加了加入线程的代码。同意,这是
public static void main(String args[]) {
AtomicInteger tally = new AtomicInteger(0);
List<Thread> threadList = new ArrayList<Thread>();
for (int i = 0; i < 10; i++) {
Thread t = new Thread(new DoThing(tally));
t.start();
threadList.add(t);
}
for (Thread t : threadList) {
try { t.join(); } catch (Exception e){}
}
System.out.println("Total tally: " + tally.get());
}
public static class DoThing implements Runnable {
private static final Random rand = new Random();
private final AtomicInteger tally;
public DoThing(AtomicInteger tally) {
this.tally = tally;
}
@Override public void run() {
for (int i = 0; i < 100; i++) {
int currTally = tally.incrementAndGet();
System.out.println("Thread " + Thread.currentThread().getName() + ": " + currTally);
// Random sleep to show that your threads are properly concurrently incrementing
try { Thread.sleep(rand.nextInt(10)); } catch (Exception e) {}
}
}
}