作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我怎样才能实现这里的 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 添加到 List
的 Long
.我将列表设为 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/
我是一名优秀的程序员,十分优秀!