AtomicInteger 线程安全

2024-04-02

我怎样才能实现这里的 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 of Long。我把清单列出来了CopyOnWriteArrayList https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/CopyOnWriteArrayList.html为了线程安全。我可以通过编程方式检测结果列表的大小是否不正好是 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(具有六个真正核心且无超线程)和 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直接上课。相反,使用执行者 https://docs.oracle.com/javase/tutorial/essential/concurrency/executors.htmlJava 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() );
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

AtomicInteger 线程安全 的相关文章

随机推荐

  • SQL Server Management Studio 中的宏

    有没有办法在SSMS中实现文本编辑宏 我会 例如喜欢将代码转换为如下所示 但只需按键 而不是冗长的正则表达式搜索和替换 This INSERT INTO TABLE fieldOne fieldTwo VALUES
  • Learning Swift:顶层不允许使用表达式

    我正在学习斯威夫特 我遇到了一个无法解决的问题 import UIKit func helloword str String print str helloword say I use helloword say 但 Xcode 告诉我错误
  • “int '对象不可下标”

    我开始学习GEKKO 现在 我正在解决一个 knapsak 问题来学习 但是这次我收到错误 int object is not subscriptable 你能看一下这段代码吗 问题的根源是什么 我应该如何定义 1 10 矩阵 from g
  • SWI-Prolog - 显示长列表

    我正在使用 SWI Prolog 我正在尝试打印一个列表 但如果该列表有超过 9 个项目 它看起来像那样 1 15 8 22 5 19 12 25 3 有没有办法显示整个列表 看一下 http www swi prolog org FAQ
  • 在 Yii 框架中配置数据库连接

    在Yii框架的main php文件中 有一些配置选项 这就是mysql的设置方式 db gt array connectionString gt mysql host localhost dbname testdrive emulatePr
  • Pylint 警告:可能存在不平衡的元组按顺序解包

    我有一段Python代码 def func1 a set b join map str list a return b def func2 d 1 e 2 return func1 d e def main a b c d func2 if
  • Swift 中具有共享 NSUserDefaults 的 KVO

    我在通过通信 NSUserDefaults 更改在主机应用程序及其扩展之间进行通信时遇到问题 我初始化了NSUserDefaults using init suiteName 添加 KVO 观察者使用addObserver 方法并覆盖该方法
  • Lombok 未在 Netbeans 项目中工作

    我想在项目中使用Lombok来使用 Getter和 Setter 我包括使用 Maven
  • 显示图像的片段中的内存问题

    我正在使用片段来显示图像 页面 我有一个活动 主要 其中包含所有片段 package com example hscroll demo import android os Bundle import android preference P
  • 为 POCO 实施 IEquatable

    我注意到 EF 的 DbSet Add 非常慢 谷歌搜索了一下 找到了一个 SO 答案 承诺性能提升高达 180 倍 https stackoverflow com a 7052504 141172 https stackoverflow
  • 计算 SQL 中特定事件之前和之后的事件数量?

    我有一个包含日期和事件的表 有一个名为 A 的事件 我想知道 Sql Bigquery 中事件 A 之前和之后发生了多少个事件 例如 User Date Events 123 2018 02 13 D 123 2018 02 12 B 12
  • 从网络数据抓取类返回数据?

    我正在尝试创建一个类 它可以让我从网络服务获取请求的数据 我被困在如何返回值上 FooClass m DataGrabber is the class which is supposed to get values dataGrabber
  • R:使用矢量化按间隔分配值

    让我们有一个数字向量 a lt round runif 20 1 5 0 1 3 5 4 2 1 2 3 4 5 2 我需要使用如下表为这些数字分配值 1 to 2 assign A 3 to 4 assign B 5 assign C 这
  • Ruby Mixins 和实例变量

    是否有将参数传递给混合方法的最佳实践方法 使用 mixin 的类可以设置混合方法期望的实例变量 或者可以将所有必要的参数作为参数传递给混合方法 背景是我们有一个 Rails 控制器来发布内容 但其他控制器甚至模型都需要能够 充当发布者 所以
  • 错误“来源:系统进程已退出,因此请求的信息不可用”

    它在我的电脑上可以工作 但是当我放入另一台机器时 我收到错误 源 系统进程已退出 因此请求的信息不可用 并且 exe 没有出来 有哪位有经验的兄弟可以帮忙吗 赞赏 p New Process With p EnableRaisingEven
  • GooglePlayServices Admob 问题:“无法加载广告:0”

    我对新的 admob 有疑问 这是我的代码 尝试在我的主要活动中创建和加载广告 private void createAndLoadAd String adUnitID RelativeLayout rlRoot View upperVie
  • 如何创建在特定条件下对另一列进行计数的列?右

    下面 数据已被重新调整 并列出了输入和预期输出 Data structure list record id c 110101 110101 110101 110101 110101 110101 110101 110101 110101 1
  • 如何为 ruby​​ on Rails 创建 .htaccess?

    有谁知道创建 htaccess在铁轨上 请指导我 谢谢 regards 您只需在网站文档根目录中创建 htaccess 文件即可 在 apache 中 这将是您网站的文档根目录 可能类似于 var www your website com
  • 将 KeyVaultClient 与 MSAL 令牌“未经授权”结合使用

    桌面应用程序如何使用 Azure AD 读取 KeyVault 机密 我能够获取 MSAL 令牌 但将其交给 KeyVaultClient 始终会导致 Microsoft Azure KeyVault Models KeyVaultErro
  • AtomicInteger 线程安全

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