7

我想发出一个 HTTP 请求,然后得到如下所示的响应:

URLConnection c = new URL("http://foo.com").openConnection();
c.setDoOutput(true);

/* write an http request here using a new OutputStreamWriter(c.getOutputStream) */

BufferedReader reader = new BufferedReader(new InputStreamReader(c.getInputStream));
reader.readLine();

但我的问题是,如果我发送的请求需要很长时间才能收到响应,那么上面的调用 reader.readLine() 会发生什么?这个进程会在 CPU 上保持运行/可运行,还是会从 CPU 中取出并在有 IO 被读取时被通知唤醒并再次运行?

如果它停留在 CPU 上,有什么办法让它下车并在以后得到通知?

4

2 回答 2

21

其他人说的都是对的。java.io 中的 Java 的“旧 I/O”库包含阻塞调用。但他们不忙等待。它们在 I/O 上阻塞,一旦 I/O 可用,内核将重新调度它们。

我不是很确定,所以我自己试了一下。采取这个示例类:

import java.io.*;

public class Test {

  public static void main(String[] args) throws IOException {
    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

    String line = reader.readLine();
    System.out.println(line);
  }
}

并在命令行上编译它。然后运行它,但不要输入任何内容。在您输入字符之前,该程序应该阻止输入,并且在您输入 enter 之前它不会超过 readline。ps应该能够告诉我们有关此过程的更多详细信息。使用该a标志从以下位置获取更多详细信息ps

japeters@<computer-name>] ps a
  PID   TT  STAT      TIME COMMAND
 3846 s000  S      0:00.16 -zsh
 3992 s000  S+     0:00.40 /usr/bin/java Test

PS的手册页说:

state 状态由一系列字符给出,例如,“RWNA”。第一个字符表示进程的运行状态:

  • I 标记一个空闲的进程(睡眠时间超过大约 20 秒)。
  • R 标记一个可运行的进程。
  • S 标记睡眠时间少于 20 秒的进程。

因为我刚刚开始这个过程,所以S是有道理的。进程处于休眠状态,等待操作系统调度。实际上,如果您检查top,您会注意到该进程占用了 0% 的 CPU。

所以不用担心这个调用的性能,没有忙碌的等待或轮询:系统会为你处理 I/O 事件,并且会智能地处理你的进程。

于 2010-05-20T11:42:08.107 回答
-3

一个好的操作系统会有一个调度程序,将进程置于阻塞或类似状态,任何任务切换都不会切换到阻塞进程。

例如,windows 中的空闲进程是在没有准备好运行的进程(休眠、阻塞等)时运行的。

于 2010-05-05T22:43:30.527 回答