2

如果我有以下虚拟代码:

public static void main(String[] args) {
  TestRunnable test1 = new TestRunnable();
  TestRunnable test2 = new TestRunnable();
  Thread thread1 = new Thread(test1);
  Thread thread2 = new Thread(test2);
  thread1.start();
  thread2.start();
}

public static class TestRunnable implements Runnable {
  @Override
  public void run() {
    while(true) {
      //bla bla
    }
  }
}

在我当前的程序中,我有一个类似的结构,即两个线程执行相同的 Run() 方法。但是由于某种原因,只有线程 1 获得了 CPU 时间,即线程 2 永远没有机会运行。这是因为线程 1 在其 while 循环中,线程 2 等待吗?

我不太确定,如果一个线程处于一个while循环中,它是否会“阻塞”其他线程?我会这么认为,但不是 100% 肯定,所以很高兴知道是否有人可以告诉我这里实际发生的事情。

编辑 好的,只是再次尝试制作一个非常简单的示例,现在两个线程都在获取 CPU 时间。但是,在我的原始程序中并非如此。一定是某个地方的一些错误。现在正在调查。感谢大家清理它,至少我得到了那个知识。

4

4 回答 4

7

JVM 不能保证它会停止一个繁忙的线程来给其他线程一些 CPU。

call 是一个很好的做法Thread.yield();,或者如果这不起作用 call Thread.sleep(100);,在你的忙循环中让其他线程拥有一些 CPU。

于 2012-11-19T23:21:27.653 回答
1

在某些时候,现代操作系统会抢占当前上下文并切换到另一个线程 - 但是,它也会(总体上是一个相当愚蠢的事情)将 CPU 变成烤面包机:这个小的“繁忙循环”可能正在计算校验和,让它运行缓慢将是一种耻辱!

出于这个原因,通常建议sleep/yield手动 - 甚至是sleep(0)1 - 这将在操作系统决定控制之前产生线程执行。在实践中,对于给定的空循环代码,这将导致手动让步时 CPU 使用率从 99% 变为 0%。(实际数字将根据每个循环完成的“工作”等而有所不同。)


1产生线程/上下文的最短时间因操作系统和配置而异,这就是为什么并不总是希望产生 - 但是 Java 和“实时”通常不会出现在同一个句子中。

于 2012-11-19T23:39:34.480 回答
0

实际的线程调度应该由操作系统而不是 Java 处理。这意味着每个线程应该被赋予相同的运行时间(尽管不是按可预测的顺序)。在您的示例中,每个线程将在其处于活动状态时旋转并且不执行任何操作。如果您在 while 循环中执行此操作,您实际上可以看到这种情况发生System.out.println(this.toString())。您应该看到每个线程都可以打印出来。

为什么你认为一个线程占主导地位?

于 2012-11-19T23:22:46.777 回答
0

操作系统负责调度线程。这在几年前发生了变化。它在不同的操作系统(Windows/Linux 等)之间有所不同,并且很大程度上取决于 CPU 的数量和运行的代码。如果代码不包含一些等待功能,如 Thread.yield() 或监视器上带有 wait() 方法的同步块,CPU 很可能会让线程长时间运行。
拥有具有多个 CPU 的机器将提高应用程序的并行性,但是在不允许其他线程在多线程环境中运行的线程的 run() 方法中编写代码是一种糟糕的编程。

于 2012-11-19T23:27:08.153 回答