为什么SocketTimeoutException使程序冻结?

时间:2015-04-29 08:04:36

标签: java multithreading freeze executorservice socket-timeout-exception

我为我的程序提供超过600个链接,存储在ArrayList以获取网页的标题,使用JSoup(以及其他)。对于每个链接(使用 for 循环),我创建一个新线程(使用thread.start())并通过我的程序传递链接,我等待我的线程完成({{1在启动一个新线程之前(同时执行会导致一些问题,我这样做是为了防止意外的线程结束停止其他链接的执行)。

问题是有时候,JSoup会抛出一个SocketTimeoutException(我应该抓住它),这会让我的程序冻结。我不知道为什么即使用thread.join包围执行也会停止。

这是我的一段代码,也许可以帮助您理解:

try/catch

在我的过程中:

// In the method actionPerformed() of my JPanel

for(final String link : links)
{
    Thread t = new Thread()
    {
        public void run()
        {
            Analyzer.process(link);
        }
    };
    t.start();
    try 
    {
        t.join();
    } 
    catch (InterruptedException e) 
    {
        e.printStackTrace();
    }
}

这很烦人,因为这个过程很长,我让它运行一夜,今天发现我的程序冻结了第54个链接。 ^^'提前谢谢你!

编辑 - 更新

SercanOzdemir建议我使用ExecutorService,而不是创建线程并使start() - join(),所以我尝试了:

// method process() of my Analyzer class
try 
{
    Document doc = Jsoup.connect(lien).userAgent("Mozilla").timeout(5*10000).get(); 
    //                    ^ EXCEPTION THROWN HERE ! ^

    title = doc.title();
}
catch (Exception e) 
{
    e.printStackTrace();
    erreurs+="Erreur lors de la lecture du titre\n";
}

但它只打印我的调试链接。知道为什么它不运行我的过程吗?

2 个答案:

答案 0 :(得分:1)

为每个链接打开一个新线程是一个非常糟糕的选择。

如果你想要一个多线程程序,请考虑使用ExecutionService

如果我们遇到你的问题,我宁愿改变这个程序,就像下面一样,因为你在连接部分捕获一个异常并且不能保证你的异常已被抛出这部分..

new Runnable(){

            @Override
            public void run(){
                try{
                    // your codes
                }
                catch( Exception e ){
                    e.printStackTrace();
                }

            }
        }.run();

答案 1 :(得分:1)

我没有尝试使用jsoup,但这是一种创建线程来执行任务并监控其状态的简单方法。

    ExecutorService executorService = Executors.newCachedThreadPool();
    Future future = null;
    for(final String link : links)
    {
        future = executorService.submit(new Runnable(){

        @Override
        public void run(){
            try{
               Analyzer.process(link);
            }
            catch( Exception e ){
                e.printStackTrace();
            }

        }
    });

        while(future != null
                && !future.isDone()
                && !future.isCancelled())
        {
            try {
                Thread.sleep(2000); // Or do something else
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    executorService.shutdown();

更新后的问题中的代码无效,因为您正在创建服务并立即覆盖它而无需等待它完成。

ExecutorService ex = Executors.newSingleThreadExecutor();
for(final String link : links)
{
  System.err.println("-- "+i+" --");              //DEBUG
  ex.execute(new Runnable(){ //Here it is created
        @Override
        public void run(){
            try
            {
                Analyzer.process(link);
            }
            catch( Exception e )
            {
                e.printStackTrace();
            }

        }
});
i++;                                            //DEBUG
//a split second later this loop finishes and overwrites the service again
}
ex.shutdown();