java - 如何在多线程程序中保存线程变量的值

标签 java multithreading executorservice

我有一段代码,每 5 秒生成一个新线程,每个线程定期打印出计数器的值。它总共启动最多 10 个线程。

代码如下:

public static void main(String[] args) {
    ScheduledExecutorService task = Executors.newScheduledThreadPool(10);
    AtomicInteger counter = new AtomicInteger(0);
    int i = 0;
    while (i < 10) {
        // sleep 5 seconds
        sleep(5);
        task.scheduleAtFixedRate(() -> {
            String threadName = Thread.currentThread().getName();
            int newCounter = counter.get();
            System.out.println(String.format("[%s] counter = %d" , threadName, newCounter));
        }, 0, 2, TimeUnit.SECONDS);

        counter.getAndIncrement();
        ++i;
    }
}

private static void sleep(int sleepTime) {
    try {
        TimeUnit.SECONDS.sleep(sleepTime);
    } catch (InterruptedException ie) {

    }
}

这是输出:

[pool-1-thread-1] counter = 1
[pool-1-thread-1] counter = 1
[pool-1-thread-2] counter = 1
[pool-1-thread-3] counter = 1
[pool-1-thread-1] counter = 2
[pool-1-thread-2] counter = 2
[pool-1-thread-4] counter = 2
[pool-1-thread-5] counter = 2
[pool-1-thread-3] counter = 2
[pool-1-thread-1] counter = 3
[pool-1-thread-7] counter = 3
[pool-1-thread-6] counter = 3
[pool-1-thread-8] counter = 3
[pool-1-thread-4] counter = 3
[pool-1-thread-9] counter = 3
[pool-1-thread-5] counter = 3
[pool-1-thread-10] counter = 3
[pool-1-thread-1] counter = 4
   .......

我希望每个线程都打印出其原始值,例如,pool-1-thread-1应该始终打印出0或1(取决于计数器是先递增还是线程先启动),第二个线程应该持久地发出先前的计数器+1,...如下所示:

[pool-1-thread-1] counter = 1
[pool-1-thread-1] counter = 1
[pool-1-thread-2] counter = 2
[pool-1-thread-3] counter = 3
[pool-1-thread-1] counter = 1
[pool-1-thread-2] counter = 2
[pool-1-thread-4] counter = 4
[pool-1-thread-5] counter = 5
[pool-1-thread-3] counter = 3
[pool-1-thread-1] counter = 1
[pool-1-thread-7] counter = 7
  .......

我的问题是如何使 newCounter 局部变量在每个线程中保持其原始值。我能想到的方法是将线程名称到其原始值的映射存储在线程安全哈希表中。有没有更清洁的方法来实现这一点?谢谢

最佳答案

要将值绑定(bind)到特定线程,您可以使用 ThreadLocal多变的。 javadoc 中的 ThreadId 示例类可以轻松调整来解决您的用例。

public static void main(String[] args) {
    ScheduledExecutorService task = Executors.newScheduledThreadPool(10);
    AtomicInteger counter = new AtomicInteger(0);
    ThreadLocal<Integer> id = ThreadLocal.withInitial(counter::incrementAndGet);
    int i = 0;
    while (i < 10) {
        // sleep 5 seconds
        sleep(5);
        task.scheduleAtFixedRate(() -> {
            String threadName = Thread.currentThread().getName();
            System.out.println(String.format("[%s] counter = %d" , threadName, id.get()));
        }, 0, 2, TimeUnit.SECONDS);

        ++i;
    }
}

private static void sleep(int sleepTime) {
    try {
        TimeUnit.SECONDS.sleep(sleepTime);
    } catch (InterruptedException ie) {

    }
}

关于java - 如何在多线程程序中保存线程变量的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50360604/

相关文章:

python - TkInter 在线程运行时禁用按钮

java - FixedThreadPool 和 ExecutorCompletionService 的 OutOfMemory 错误

java - 生成三维随机数空间的算法

java - 将数据从 Excel 传递到 Web 服务

java - 从 Facebook 下载用户个人资料图片 : AsyncTask or HandlerThread

Java 多线程服务器 - 每个连接都返回数据。在主线程处理?

java - 线程池问题-收集文件

java - Java中的MongoDB查询,在嵌套对象中搜索/查找

java - 如何在 Android 程序的 Eclipse 中将变量声明为 OpenGL 的 GLuint 类型?

c++ - 解锁对 STL vector::size 安全性的访问