1

在一次采访中,有人问我一个编码问题,我必须在该代码中找到问题并提出适当的解决方案。

请在下面找到整个代码:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

public class Atomic {

    static AtomicInteger count = new AtomicInteger(0);
    static int counter = 0;

    public static class Runnable extends Thread {

    public void run() {
        while (count.getAndSet(1) != 0) {
            try {
                Thread.sleep(3000);
            } catch (Exception e) {

            }
        }
        counter = counter + 1;
        count.set(0);
    }

}

public static void main(String[] args) {
    ExecutorService executor = Executors.newFixedThreadPool(10);
    for (int i = 0; i < 10; i++) {
        Runnable runnable = new Runnable();
        executor.execute(runnable);
    }
    executor.shutdown();
}

}

此代码运行正常。但问题是,如果线程数增加或者我运行 For 循环近 10000 次,这段代码中就会出现一些问题。

我试图找出问题所在,但找不到问题。

4

1 回答 1

3

这段代码有几个问题。你没有说“有一些问题”的意思,但这里有一些东西跳出来。


首先,counter变量没有安全更新。多个线程不能保证最后写入值的可见性;您也不能保证在读取和写入之间没有其他线程更新其值。

对此的简单解决方案:更改counterAtomicInteger, 并使用getAndIncrementorincrementAndGet增加它。


其次,public static class Runnable extends Thread {非常可疑

  1. 不要隐藏常见的 Java 类的名称(这是隐藏java.lang.Runnable
  2. 不要Thread直接扩展,尤其是当您只需要java.lang.Runnable添加一个ExecutorService.

更合适的类声明是:

public static class MyRunnable implements Runnable {

(或者你想怎么称呼它)

或者你可以只声明一个匿名类:

executor.execute(new Runnable() { /* body */ });

或者你可以只声明一个 lambda:

executor.execute(() -> { /* body */ });

第三,count这里似乎并没有真正起到明显的作用。可运行的逻辑似乎是:

  • 如果“标志”为假:
    1. 将“标志”设置为真
    2. 增加一个变量
    3. 将“标志”设置为假
  • 否则:
    1. 等待 3 秒
    2. 再试一次

count在这里扮演着“旗帜”的角色。它实际上只是一个AtomicBoolean.

但是,如果您制作an ,则根本不需要单独的count变量:counterAtomicInteger

while (true) {
  int current = counter.get();
  if (counter.compareAndSet(current, current + 1)) {
    // Nothing else is trying to update "current" at the same time:
    // we updated it. Stop.
    break;
  }

  // Something else is trying to update at the same time.
  // Sleep for 3 seconds.
  Thread.sleep(3000);
}
于 2020-02-26T08:07:34.123 回答