【问题标题】:How does a thread move from running to runnable state?线程如何从运行状态转变为可运行状态?
【发布时间】:2016-04-25 19:25:38
【问题描述】:

我想知道线程如何以及何时在可运行状态和运行状态之间来回移动。幕后实际发生了什么。我想在 ThreadPool 的情况下需要这样做,但我无法完全理解。请帮助我理解这一点。

【问题讨论】:

  • 为什么需要知道?我也不知道这个,但是在没有这些知识的情况下成功使用了ThreadPool
  • 我只是想知道......如果线程处于运行状态,这意味着它正在执行 run() 方法,而当它处于可运行方法时,它正在执行 start() 方法......所以我猜从运行到可运行意味着它从运行()回到开始()......如果我错了,请纠正我,因为我是多线程的初学者
  • 线程调度是特定 JVM 的实现细节。最好的建议是将您的代码设计为不依赖于调度技巧、优先级调整或 thread.yield(),因为这样的代码不可移植。让 JVM 参与线程调度。在最好的情况下,大多数时候你不需要意识到它。
  • 这个问题你指的是Thread.State(docs.oracle.com/javase/8/docs/api/java/lang/Thread.State.html)吗?我在这里看到的最接近的状态是NEWRUNNABLE,文档说线程在启动时会从前者发生变化。
  • @scottb ..感谢您的回答.....告诉我一件事从运行移回可运行意味着线程正在从 run() 方法移回 start()...做如果我错了,请纠正我

标签: java multithreading threadpool


【解决方案1】:

如果线程处于运行状态,这意味着它正在执行 run() 方法,而当它处于可运行方法时,它正在执行 start() 方法....所以我猜从 running 移动到 runnable 意味着它从 run() 回到开始()

在大多数操作系统的命名法中,“正在运行”意味着线程实际上正在某个 CPU 上执行指令,而“可运行”意味着除了 CPU 可以运行之外,没有任何东西可以阻止线程“运行”。

Java 程序无法区分这两种状态。 Java 知道的线程状态有 NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING 和 TERMINATED。

一个线程在t.start() 被调用之前是新的,之后它永远不能回到新的。 WAITING 和 TIMED_WAITING 都意味着线程正在等待其他线程中的notify() 调用。 BLOCKED 意味着它正在等待其他任何东西(例如,进入 synchronized 块),而 TERMINATED 意味着它已经完成。

【讨论】:

    【解决方案2】:

    Yield 是一个静态方法,它告诉当前正在执行的线程给线程池中具有相同优先级的线程一个机会。

    不保证Yield 会使当前执行的线程立即进入可运行状态。记住一个重要的点,yield 方法不会使线程进入等待或阻塞状态。它只能使线程从运行状态变为可运行状态。

    【讨论】:

    • yield() 很少被调用,而且它肯定不是这里起作用的主要机制。不要对非代码文本使用代码格式。
    • @Anand .....谢谢你的解释。还有一个疑问......我们将在我们的代码中手动使用yield......对吗? JVM 如何自己处理这个问题?
    • “不能保证 Yield 会立即使当前执行的线程进入可运行状态。” ...确实如此。当调用 Thread.yield() 时,JVM 完全不做任何事情是完全可以接受的。依赖于 Thread.yield() 行为的正确性的程序充其量是一个不可移植的程序,最坏的情况是一个有严重缺陷的程序。
    【解决方案3】:

    摘自 Java SCJP 认证程序员指南:线程:

    静态无效产量() 此方法会导致当前线程暂时暂停其执行,从而允许其他线程执行。由 JVM 决定是否以及何时进行此转换。

    静态无效睡眠(长毫秒)抛出 InterruptedException 当前线程在有资格再次运行之前休眠指定的时间。

    final void join() 抛出 InterruptedException final void join(long millisec) 抛出 InterruptedException 对线程上调用的这两个方法中的任何一个的调用都将等待,直到线程完成或在指定时间后超时后才返回。

    无效中断() 该方法中断调用它的线程。在 Waiting-for-notification、Sleeping 或 Blocked-for-join-completion 状态下,线程将收到 InterruptedException。

    以下示例说明了线程状态之间的转换。 (1) 处的线程在 (2) 处稍稍休眠,然后在 (3) 处循环执行一些计算,之后线程终止。 main() 方法在 (4) 处循环监视线程,打印 getState() 方法返回的线程状态。输出显示当 run() 方法开始执行时线程进入 RUNNABLE 状态,然后转换到 TIMED_WAITING 状态进入睡眠状态。唤醒时,它计算 RUNNABLE 状态的循环,并在 run() 方法完成时转换到 TERMINATED 状态。

    示例:线程状态

    public class ThreadStates {
    
      private static Thread t1 = new Thread("T1") {    // (1)
        public void run() {
          try {
            sleep(2);                                  // (2)
            for(int i = 10000; i > 0; i--);            // (3)
          } catch (InterruptedException ie){
            ie.printStackTrace();
          }
        }
      };
    
      public static void main(String[] args) {
        t1.start();
        while(true) {                                  // (4)
          Thread.State state = t1.getState();
          System.out.println(state);
          if (state == Thread.State.TERMINATED) break;
        }
      }
    }
    

    程序可能的输出:

    RUNNABLE
    TIMED_WAITING
    ...
    TIMED_WAITING
    RUNNABLE
    ...
    RUNNABLE
    TERMINATED
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-14
      • 2015-08-06
      • 2023-03-08
      相关资源
      最近更新 更多