Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为多个并行流保持一个计数器的更新_Java_Multithreading_Atomic - Fatal编程技术网

Java 为多个并行流保持一个计数器的更新

Java 为多个并行流保持一个计数器的更新,java,multithreading,atomic,Java,Multithreading,Atomic,试图维护一个(已同步)计数器以跟踪List.parallelStream。 代码如下: /** * Testing the use of AtomicInteger in List.parallelStream() */ public void UsingParallelStream() { /*Create the counter */ AtomicInteger atomicInteger = new AtomicInteger(0); /*Create an

试图维护一个(已同步)计数器以跟踪List.parallelStream。 代码如下:

/**
 * Testing the use of AtomicInteger in List.parallelStream()
 */
public void UsingParallelStream() {

    /*Create the counter */
    AtomicInteger atomicInteger = new AtomicInteger(0);

    /*Create and populate the list */
    List<Integer> numList = new ArrayList<Integer>();
    int num = 1;
    for (int i = 0; i < 1000; i++) {
        numList.add(num);
        num ++;
    }

    /*Test the consistency of the counter*/
     numList.parallelStream().forEach(number -> {
         atomicInteger.getAndIncrement();
         executeTest(atomicInteger,numList);
     });

}

private void executeTest(AtomicInteger atomicInteger, List<Integer> l) {
    if (atomicInteger.intValue() % 100 == 0) {
        System.out.println(l.get(atomicInteger.intValue() - 1));
    }
}
/**
*测试List.parallelStream()中AtomicInteger的使用
*/
使用ParallelStream()的公共void{
/*创建计数器*/
AtomicInteger AtomicInteger=新的AtomicInteger(0);
/*创建并填充列表*/
List numList=new ArrayList();
int num=1;
对于(int i=0;i<1000;i++){
numList.add(num);
num++;
}
/*测试计数器的一致性*/
numList.parallelStream().forEach(编号->{
atomicInteger.getAndIncrement();
executeTest(原子整数,numList);
});
}
私有void executeTest(AtomicInteger,列表l){
if(atomicInteger.intValue()%100==0){
System.out.println(l.get(atomicInteger.intValue()-1));
}
}
以下是结果(您可以看到计数器未同步): 100 200 300 300 401 501 501 701 800 901 800 一千

谢谢你,布莱斯,
David.

executeTest(atomicInteger,numList)中的操作不是原子的

if (atomicInteger.intValue() % 100 == 0) {
    System.out.println(l.get(atomicInteger.intValue() - 1));
}
当发现线程
atomicInteger.intValue()%100==0
为true时,尝试执行
System.out.println(l.get(atomicInteger.intValue()-1)),其他线程可能已更新该值

如何解决?使用局部变量:

numList.parallelStream().forEach(number -> {
    int local = atomicInteger.getAndIncrement();
    executeTest(local,numList);
});


private void executeTest(int  local, List<Integer> l) {
    if (local % 100 == 0) {
        System.out.println(l.get(local - 1));
    }
}
numList.parallelStream().forEach(数字->{
int local=atomicInteger.getAndIncrement();
执行测试(本地、numList);
});
私有void executeTest(int-local,列表l){
如果(本地%100==0){
System.out.println(l.get(local-1));
}
}

您需要确保每个线程在不同的值上运行。此值只能找到一次,并且只能通过
getAndIncrement
的返回值找到。对原子整数的每次进一步读取操作都可能返回一个新值,该值属于另一个线程

numList.parallelStream().forEach(number -> {
        var value = atomicInteger.getAndIncrement();
        executeTest(value, numList);
});

private void executeTest(int value, List<Integer> l) {
    if (value % 100 == 0) {
        System.out.println(l.get(value - 1));
    }
}
numList.parallelStream().forEach(数字->{
var value=atomicInteger.getAndIncrement();
executeTest(值,numList);
});
私有void executeTest(int值,列表l){
如果(值%100==0){
System.out.println(l.get(value-1));
}
}

首先递增,然后读取时,多个线程可能使用相同的值。原子意味着,每个操作都是原子的。这并不意味着在同一个线程中有多个操作是原子的。

对不起,这是完整的代码:它仍然不是完整的代码。哪里添加了
executeTest
缺少的代码。这有什么关系?请详细说明一下,如果
getAndIncrement()
是原子的,这难道不意味着所有线程在任何时候都看到相同的值吗?我想我看到了一个例子:在if语句之后,thread get context switch。因此,在JVM唤醒线程之后,该值可能会有所不同,这是一个有效的示例吗?一旦我将atomicInteger传递给executeTest方法,那么它将只在本地看到,而不会在方法之外递增。请参见示例:private void executeTest(AtomicInteger计数器,列表l){if(counter.intValue()%100==0){System.out.println(l.get(counter.intValue()-1));}}}问题是操作调用了两次
AtomicInteger.intValue
。下面是一个示例,thread1找到了
atomicInteger.intValue
为100,并尝试打印它。同时,thread2将
atomicInteger
更新为101,因此当thread1再次检索该值时,它将得到101。