1

我尝试创建一个扩展线程的类,它只需要一个字符串数组并交替打印前 2 个字符串以进行 10000 次迭代。我使用 AtomicInteger(计数器)跟踪要打印的索引,但是输出有时会打印:hello hello hello w hello hello 等,而不是在每次迭代时交替。为什么会这样?如果不将“同步”放在运行方法中,我该如何解决?

public class MyThreadDelegate implements Runnable {

  List<String> words;
  AtomicInteger counter = new AtomicInteger(0);

  public MyThread(List<String> words) {
    this.words = words;
  }

  @Override
  public void run() {
    for (int i = 0; i < 10000; i++) {
      System.out.println(words.get(counter.getAndIncrement()%2) + counter.get());
    }
  }

  public static void main(String[] args) {

    MyThreadDelegate myThreadDelegate = new MyThreadDelegate(Arrays.asList("hello", "w"));

    Thread t1 = new Thread(MyThreadDelegate);
    Thread t2 = new Thread(MyThreadDelegate);

    t1.start();
    t2.start();
  }
}
4

1 回答 1

0

虽然数字被一一检索,但该方法的其余部分并未同步。所以有时可能会发生这种情况:

  • t1:从计数器获取值 0
  • t2:从计数器获取值 1
  • t2:打印 w
  • t1:打印你好

一个快速的解决方法是将整个 System.out 行放在一个synchronized块中,但这不能保证线程轮流。它只是保证 echt 值在下一个值之前被检索、递增和打印。

如果您想让线程真正轮流运行,则必须实现某种锁定。但是如果你不想让线程互相等待,你为什么要使用多个线程呢?

编辑:另外,如果您打算以这种方式使用它,您可能应该让 MyThread 实现 Runnable 而不是扩展 Thread 。有关更多信息,请参阅此链接:https ://www.baeldung.com/java-runnable-vs-extending-thread (Solomon Slow 击败了我 :)

于 2019-04-26T13:16:04.910 回答