【问题标题】:Multithreaded program - Threads cutting each other off多线程程序 - 线程相互切断
【发布时间】:2016-05-24 20:30:40
【问题描述】:

我只是在测试一些线程,试图弄清楚如何使用它们。我的问题是,我怎样才能让我当前的场景按照我想要的方式工作?

我想让这个程序打印出 1 - 100。我有两种方法; oddNumbersevenNumbers

oddNumbers:

public static void oddNumbers() {
  new Thread(new Runnable() {
    public void run() {
      for (int i = 0; i < 100; i++) {
        if (i % 2 == 1) {
          System.out.println(i);
        }
      }
    }
  }).start();
}

evenNumbers:

public static void evenNumbers() {
  new Thread(new Runnable() {
    public void run() {
      for (int q = 0; q < 100; q++) {
        if (q % 2 == 0) {
          System.out.println(q);
        }
      }
    }
  }).start();
}

main method

public static void main(String[] args) {
  evenNumbers();
  oddNumbers();
}

所以,据我了解,oddNumbersevenNumbers 方法在不同的线程上运行。那么如果是,那为什么我的输出不是 1-100?

这是我得到的输出:

0
2
4
6
.
.
.
50
1
3
5
.
.
.
99
52
54
56
.
.
.
100

大约在evenNumbers 循环进行到一半时,oddNumbers 循环将其切断。为什么会发生这种情况,我该如何设置它才能打印 1-100?

提前致谢!

【问题讨论】:

  • 好吧,偶数线程先于奇数线程启动……但即使它们同时开始,您为什么认为它们会交替出现?
  • 与程序的实际执行时间相比,您的输出缓冲区更有可能填充并刷新到输出。加上时间戳,您可能会看到更多重叠。
  • 让我想起:'一个程序员遇到了问题。他心想:“我知道了,我会用线来解决的!”。有现在的问题。两个他'
  • @Kaelinator “同一时间”是什么意思?线程可能在多核上同时运行,但 System.out.print 有一个同步块,用于序列化写入
  • @Kaelinator 好吧,就像我说的,你先启动一个线程——所以它会在另一个线程启动之前通过它的数字;然后另一个开始并“切断”第一个线程。

标签: java multithreading


【解决方案1】:

因为您没有告诉线程等待剩余的参与者。

很难判断下一个线程在启动后是否继续工作,或者需要多长时间才能启动。可能是几个 cpu 周期或 2 秒。

您想要实时关键应用程序的准确指令时间?开始 fpga 编程。

对于这个 java pc 程序,您可以使用循环屏障让它们一起执行步骤,而没有任何起始优先级重要性。

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class Demo {
    public static CyclicBarrier barrier = new CyclicBarrier(2);
    public static void oddNumbers() {
          new Thread(new Runnable() {
            public void run() {
              for (int i = 0; i < 100; i++) {
                  try {
                    barrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                if (i % 2 == 1) {
                  System.out.println(i);
                }
              }
            }
          }).start();
        }


        public static void evenNumbers() {
          new Thread(new Runnable() {
            public void run() {
              for (int q = 0; q < 100; q++) {
                  try {
                    barrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                if (q % 2 == 0) {
                  System.out.println(q);
                }
              }
            }
          }).start();
        }


        public static void main(String[] args) {
          evenNumbers();
          oddNumbers();
        }
}

在这里创建了屏障实例,其中有 2 个线程的空间,因此每 2 个等待操作都会重置它,并且线程可以在下一次迭代时再次等待它。

仍然有概率输出:

1
0
3
2
5
4
...

而不是

0
1
2
3

可以使用第三个动作来解决,在打印到控制台之前合并 2 个线程结果。

这里的难点是您要求在多线程环境中执行串行操作。

【讨论】:

    【解决方案2】:

    我知道你不希望它们被交替,只要理解为什么每个都被执行这么长时间。

    该决定由操作系统的调度程序做出。它决定何时切换到另一个线程。您的示例的问题是您的线程非常小,它们执行得非常快。

    调度程序赋予线程执行一段时间的权力,问题是,这段时间足以显示你的循环的这么多数字,所以它们不会被多次切换。

    如果你让它运行更长时间,使用更大的数字,你会得到更好的结果。或者,您也可以让循环在打印之前花费更长的时间,添加一些需要时间的微积分,这样它就不会连续打印那么多数字。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-14
      • 1970-01-01
      • 2023-03-18
      • 2010-12-09
      • 2015-07-27
      • 1970-01-01
      • 1970-01-01
      • 2021-08-20
      相关资源
      最近更新 更多