【问题标题】:Stop thread execution when it calls url.openStream() in a loop在循环中调用 url.openStream() 时停止线程执行
【发布时间】:2023-09-21 23:43:01
【问题描述】:

编辑:我知道 Thread.interrupt() 做了什么。

  • while (!Thread.currentThread().isInterrupted()) 在我中断线程时不会退出。
  • 我还尝试从 url.openStream() 中捕获异常;当。。。的时候 线程被中断(绝望,也许是阻塞方法, 不是)并退出循环,没有任何成功。

应用程序创建一个Thread,它连续读取一个URL。 3 秒后,Thread 被中断但不幸的是继续执行。

如何停止线程执行?

代码(Main.java、MyRunnable.java):

public class Main {

    public static void main(String[] args) {
        MyRunnable runnable = new MyRunnable("http://ninjaflex.com/");
        Thread thread = new Thread(runnable);
        thread.start();
        sleep(3000);
        thread.interrupt();
        System.out.println("Thread.interrupt() invoked.");
    }

    private static void sleep(long timeMilli) {
        try {
            Thread.sleep(timeMilli);
        } catch (Exception e) {

        }
    }
}

public class MyRunnable implements Runnable {

    private String website;

    MyRunnable(String website) {
        this.website = website;
    }

    @Override
    public void run() {
        URL url = createUrl();
        if (url != null) {
            while (!Thread.currentThread().isInterrupted()) {
                sleepOneSec();
                readFromUrl(url);
                System.out.println("Read from " + website);
            }
            System.out.println("Script: Interrupted, exiting.");
        }
    }

    private URL createUrl() {
        URL url = null;
        try {
            url = new URL(website);
        } catch (MalformedURLException e) {
            System.out.println("Wrong URL?");
        }
        return url;
    }

    private void sleepOneSec() {
        try {
            Thread.sleep(1000);
        } catch (Exception e) {
            System.out.println("Error sleeping");
        }
    }

    private void readFromUrl(URL url) {
        InputStream in = null;
        try {
            in = url.openStream();
        } catch (Exception e) {
            System.out.println("Exception while url.openStream().");
            e.printStackTrace();
        } finally {
            closeInputStream(in);
        }
    }

    private void closeInputStream(InputStream in) {
        try {
            in.close();
        } catch (IOException e) {
            System.out.println("Error while closing the input stream.");
        }
    }
}

【问题讨论】:

  • 我知道 Thread.interrupt() 做了什么亲爱的@PM77-1,但如果我在这里做错了什么,请分享。

标签: java concurrency interrupt interrupt-handling


【解决方案1】:

基本上,您的MyRunnable 线程在睡眠期间被中断。 InterreuptedException 被抛出但被捕获。顺便说一句,抓住Exception 是一个坏习惯,你不应该那样做。 来自javadoc:“抛出此异常时清除当前线程的中断状态”。 因此,您的 while 循环将永远不会看到该标志。

【讨论】:

  • 哦,我没想到会这样。让我通过删除睡眠来检查。但这似乎合乎逻辑。感谢您的贡献。
  • 好吧,我错过了那个场景:"如果这个线程在调用对象的 wait()、wait(long) 或 wait(long, int) 方法时被阻塞或该类的join()、join(long)、join(long, int)、sleep(long)或sleep(long, int)等方法,则其中断状态将被清除 它将收到一个 InterruptedException。".再次感谢。
【解决方案2】:

用简单的 Thread.sleep 调用替换对 sleepOneSec 方法的调用。在您的while 循环外部 捕获 InterruptedException。这将导致循环自然退出:

try {
    while (true) {
        Thread.sleep(1000);
        readFromUrl(url);
        System.out.println("Read from " + website);
    }
} catch (InterruptedException e) {
    System.out.println("Script: Interrupted, exiting.");
}

【讨论】:

  • 是的,可以。但我不在乎删除睡眠电话。老实说,我把它放在那里是为了不被原木轰炸。
  • 被“脚本:中断,退出”轰炸你的意思是?只需将其更改为System.getLogger(Main.class.getName()).log(System.Logger.Level.DEBUG, "Script: Interrupted, exiting.", e);,这样只有在您更改日志配置时才会看到它。
  • 非常感谢@VGR!
  • 你会相信我在一个android应用程序中有相同的代码,并且线程的执行没有停止吗?提示,那里没有 Thread.sleep() 。可能会再问一次。
【解决方案3】:

我删除了 MyRunnable.sleepOneSec 并且您的代码开始工作。

【讨论】:

  • 是的,这就是解决方案。 sleep() 正在捕获中断,但随后中断状态已清除,因此无法退出循环。
最近更新 更多