如何停止在 Java 中等待阻塞读操作的线程?

发布于 2024-10-02 20:34:35 字数 434 浏览 5 评论 0原文

我有一个执行以下代码的线程:

public void run() {
    try {
        int n = 0;
        byte[] buffer = new byte[4096];
        while ((n = in.read(buffer)) != -1) {
            out.write(buffer, 0, n);
            out.flush();
        }
    } catch (IOException e) {
        System.out.println(e);
    }
}

其中 inSystem.in。我怎样才能优雅地停止这样的线程?关闭 System.in 和使用 Thread.interrupt 似乎都不起作用。

I have a thread that executes the following code:

public void run() {
    try {
        int n = 0;
        byte[] buffer = new byte[4096];
        while ((n = in.read(buffer)) != -1) {
            out.write(buffer, 0, n);
            out.flush();
        }
    } catch (IOException e) {
        System.out.println(e);
    }
}

where in is System.in. How can I stop such thread gracefully? Neither closing System.in, nor using Thread.interrupt appear to work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

孤蝉 2024-10-09 20:34:35

这是因为读取 System.in (InputStream) 是一个阻塞操作。

看看这里 是吗可以从输入流中读取超时吗?

This is because reading System.in (InputStream) is a blocking operation.

Look here Is it possible to read from a InputStream with a timeout?

千秋岁 2024-10-09 20:34:35

您偶然发现了一个 9 年前的bug,没有人愿意修复。他们说此错误报告中有一些解决方法。最有可能的是,您需要找到其他方法来设置超时(忙碌等待似乎是不可避免的)。

You've stumbled upon a 9 year old bug no one is willing to fix. They say there are some workarounds in this bug report. Most probably, you'll need to find some other way to set timeout (busy waiting seems unavoidable).

森罗 2024-10-09 20:34:35

您可以使用 available() 方法(非阻塞)来检查是否有任何内容可以预先读取。

在伪java中:

//...
while(running)
{
    if(in.available() > 0)
    {
        n = in.read(buffer);
        //do stuff with the buffer
    }
    else
    {
        Thread.sleep(500);
    }
}
//when running set to false exit gracefully here...

You could use the available() method (which is non-blocking) to check whether there is anything to read beforehand.

In pseudo-java:

//...
while(running)
{
    if(in.available() > 0)
    {
        n = in.read(buffer);
        //do stuff with the buffer
    }
    else
    {
        Thread.sleep(500);
    }
}
//when running set to false exit gracefully here...
善良天后 2024-10-09 20:34:35

在其他线程中关闭流是否安全?
这对我有用。在这种情况下,in.read(...) 抛出异常 SocketException

Is it safe to close in stream in other thread?
It works for me. In this case, in.read(...) throws exception SocketException.

醉生梦死 2024-10-09 20:34:35

如果您想给用户一些时间来输入数据(可能是为了允许覆盖默认值或中断某些自动化过程),那么首先等待并在暂停后检查可用的输入:

System.out.println("Enter value+ENTER within 5 Seconds to override default value: ");
try{
  Thread.sleep(5000);
} catch {InterruptedException e){}

try{
  int bytes = System.in.available();
  if (bytes > 0) {
    System.out.println("Using user entered data ("+size+" bytes)");
  } else {
    System.out.println("Using default value"); 
  }
} catch(IOException e) { /*handle*/ }

If you want to give a user some time to enter data - maybe to allow overriding default values or interrupting some automated process -, then wait first and check available input after the pause:

System.out.println("Enter value+ENTER within 5 Seconds to override default value: ");
try{
  Thread.sleep(5000);
} catch {InterruptedException e){}

try{
  int bytes = System.in.available();
  if (bytes > 0) {
    System.out.println("Using user entered data ("+size+" bytes)");
  } else {
    System.out.println("Using default value"); 
  }
} catch(IOException e) { /*handle*/ }
傾城如夢未必闌珊 2024-10-09 20:34:35

我今天遇到了同样的问题,这就是我使用 in.ready() 修复它的方法:

public void run() {
    String line;
    // Some code

    while(!Thread.currentThread().isInterrupted()){
        try {
            if (in.ready()) {
                line = in.readLine();
            } 
        } catch (Exception e) {
            try {
                Thread.currentThread().wait(500);
            } catch (InterruptedException e1) {
                // Do what we want when thread is interrupted
            }
        }
    }
}

I had the same problem today, and this is how I fixed it, using in.ready() :

public void run() {
    String line;
    // Some code

    while(!Thread.currentThread().isInterrupted()){
        try {
            if (in.ready()) {
                line = in.readLine();
            } 
        } catch (Exception e) {
            try {
                Thread.currentThread().wait(500);
            } catch (InterruptedException e1) {
                // Do what we want when thread is interrupted
            }
        }
    }
}
爱冒险 2024-10-09 20:34:35

您可以为此使用外部标志

boolean flag = true;


public void run() { 
    try { 
        int n = 0; 
        byte[] buffer = new byte[4096]; 
        while ((n = in.read(buffer)) != -1 && flag) { 
            out.write(buffer, 0, n); 
            out.flush(); 
        } 
    } catch (IOException e) { 
        System.out.println(e); 
    } 
} 

you can use a external flag for this

boolean flag = true;


public void run() { 
    try { 
        int n = 0; 
        byte[] buffer = new byte[4096]; 
        while ((n = in.read(buffer)) != -1 && flag) { 
            out.write(buffer, 0, n); 
            out.flush(); 
        } 
    } catch (IOException e) { 
        System.out.println(e); 
    } 
} 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文