如何从主线程超时java线程?

Posted

技术标签:

【中文标题】如何从主线程超时java线程?【英文标题】:How to timeout a java thread from main Thread? 【发布时间】:2021-05-27 10:11:32 【问题描述】:

我不熟悉在 java 中使用 ExecutorService、Future 和 Runnable 来设置线程超时。我正在开发一个程序,我的主线程将调用另一个线程来解析 XML 文件,并且(出于安全目的)在一定时间后超时。我已经搜索了几个小时并阅读了许多 *** 线程,但我似乎根本无法让主线程中断辅助线程。当我运行这个程序时,xml 解析器将永远解析可笑的大文件,我似乎无法让它被中断。任何帮助将不胜感激。我的两个线程的代码如下。

public class xmlParser
        private static class Parse implements Runnable 

                private final String xmlFile;

                public Parse(String xmlFile) 
                        this.xmlFile = xmlFile;
                

                @Override
                public void run() 
                        try 
                                while (!Thread.interrupted()) 
                                        XMLReader xmlReader = XMLReaderFactory.createXMLReader();
                                        xmlReader.setContentHandler(new MyContentHandler());
                                        xmlReader.parse(new InputSource(xmlFile));
                        
                

                        catch (Exception e) 
                                System.err.println("TIMEOUT ERROR: Took too long to parse xml file.");
                                e.printStackTrace();

                        
                

        

    public static void main(String[] args) throws InterruptedException 
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future future = executor.submit(new Parse(args[0]));
        try 
                future.get(1, TimeUnit.SECONDS);
        
        catch (Exception e) 
                future.cancel(true);
        
        finally 
                executor.shutdownNow();
        

   

注意:我知道 future.get(long timeout, TimeUnit unit) 将抛出多种类型的异常,并将在稍后处理。目前,我只是希望我的主线程在运行 1 秒后中断 Parse 线程。

【问题讨论】:

【参考方案1】:

我试图用更简单的工作来重现:

static class FiveSecJob implements Callable<String> 
    @Override
    public  String call() 
        long t0 = System.currentTimeMillis();
        try 
            Thread.sleep(5000);
            return "success";
         catch (Exception e) 
            System.out.println("interrupted after " + (System.currentTimeMillis() - t0) / 1000d + "s: " + e);
            return e.getMessage();
        
    

@Test
public void testTimeout() 
    ExecutorService executor = Executors.newSingleThreadExecutor();
    Future<String> future = executor.submit(new FiveSecJob());
    String s = "initial value";
    try 
        s = future.get(1, TimeUnit.SECONDS);
     catch (Exception e) 
        System.out.println("cancelling future (" + e + ")");
        future.cancel(true);
     finally 
        executor.shutdownNow();
    
    System.out.println("s: " + s);

它似乎取消了像预期一样的工作。输出是:

cancelling future (java.util.concurrent.TimeoutException)
s: initial value
interrupted after 1.0s: java.lang.InterruptedException: sleep interrupted

【讨论】:

以上是关于如何从主线程超时java线程?的主要内容,如果未能解决你的问题,请参考以下文章

Java线程池

Picasso java.lang.IllegalStateException:方法调用不应该从主线程发生

Java 并发编程线程简介 ( 原子操作 | volatile 关键字使用场景 )

如何在Java中运行与主线程分开的线程?

java中异步多线程超时导致的服务异常

java在超时值后杀死线程[重复]