gpt4 book ai didi

java - AtomicInteger 线程安全

转载 作者:行者123 更新时间:2023-12-04 14:56:28 25 4
gpt4 key购买 nike

我怎样才能实现这里的 while 循环总是精确执行 100 次。当我执行代码时,在极少数情况下它会在控制台上打印 99 或 98 行而不总是 100,我不明白。

import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;

public class Print implements Runnable {
static AtomicInteger atomicInteger = new AtomicInteger(0);

@Override
public void run() {
while (atomicInteger.getAndIncrement() < 100)
System.out.println(Thread.currentThread());
}

public static void main(String[] args) throws InterruptedException {
ArrayList<Thread> threads = new ArrayList<>();

for (int i = 0; i < 5; i++)
threads.add(new Thread(new Print()));

for (Thread thread : threads)
thread.start();

for (Thread thread : threads)
thread.join();
}
}

最佳答案

无法复制您报告的体验。
在我的调试器中,这似乎是正确的,因为我在您的代码中看不到任何线程安全错误。
为了自动化进一步的测试,我按如下方式更改了您的代码。而不是打电话System.out.println , 我将线程 ID 添加到 ListLong .我将列表设为 CopyOnWriteArrayList 为了线程安全。我可以以编程方式检测结果列表的大小是否不完全是 100 个元素。

package work.basil.demo;

import java.time.Instant;
import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;

public class Print implements Runnable
{
static AtomicInteger atomicInteger = new AtomicInteger( 0 );
static CopyOnWriteArrayList < Long > list = new CopyOnWriteArrayList <>();

@Override
public void run ( )
{
while ( atomicInteger.getAndIncrement() < 100 )
//System.out.println(Thread.currentThread());
list.add( Thread.currentThread().getId() );
}

public static void main ( String[] args ) throws InterruptedException
{
System.out.println( "INFO - demo starting. " + Instant.now() );
for ( int cycle = 0 ; cycle < 1_000_000 ; cycle++ )
{
ArrayList < Thread > threads = new ArrayList <>();

for ( int i = 0 ; i < 5 ; i++ )
threads.add( new Thread( new Print() ) );

for ( Thread thread : threads )
thread.start();

for ( Thread thread : threads )
thread.join();

// System.out.println( "list.size() = " + list.size() );
// if ( list.size() == 100 ) { System.out.println( "DEBUG list.size() = " + ( list.size() ) ); }
if ( list.size() != 100 ) { System.out.println( "DEBUG list.size() = " + ( list.size() ) ); }
}
System.out.println( "INFO - demo done. " + Instant.now() );
}
}
在 Mac mini (2018) 3 GHz Intel Core i5 上运行时,该 i5 具有六个真实内核且无超线程,以及 32 GB 2667 MHz DDR4,在 IntelliJ 中使用 Java 16。运行 cycle到一百万大约需要 5 分钟。
INFO - demo starting. 2021-06-08T22:11:56.010181Z
INFO - demo done. 2021-06-08T22:16:26.982616Z
ExecutorService顺便说一句,在现代 Java 中,我们很少需要解决 Thread直接上课。相反,使用 Executors框架添加到 Java 5。
这是上面代码的修订版,重新调整以使用执行程序服务。
public static void main ( String[] args ) throws InterruptedException
{
System.out.println( "INFO - demo starting. " + Instant.now() );
for ( int cycle = 0 ; cycle < 1_000_000 ; cycle++ )
{
ExecutorService executorService = Executors.newFixedThreadPool( 5 );

int countTasks = 5;
for ( int i = 0 ; i < countTasks ; i++ )
{
executorService.submit( new Print2() );
}

executorService.shutdown();
executorService.awaitTermination( Duration.ofMinutes( 7 ).toSeconds() , TimeUnit.SECONDS );

// System.out.println( "list.size() = " + list.size() );
// if ( list.size() == 100 ) { System.out.println( "DEBUG list.size() = " + ( list.size() ) ); }
if ( list.size() != 100 ) { System.out.println( "DEBUG list.size() = " + ( list.size() ) ); }
}
System.out.println( "INFO - demo done. " + Instant.now() );
}

关于java - AtomicInteger 线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67885351/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com