Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/353.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么SocketTimeoutException使我的程序冻结?_Java_Multithreading_Freeze_Executorservice_Socket Timeout Exception - Fatal编程技术网

Java 为什么SocketTimeoutException使我的程序冻结?

Java 为什么SocketTimeoutException使我的程序冻结?,java,multithreading,freeze,executorservice,socket-timeout-exception,Java,Multithreading,Freeze,Executorservice,Socket Timeout Exception,我给我的程序提供了600多个链接,存储在ArrayList中,使用JSoup(以及其他)获取网页标题。对于每个链接(使用For循环),我创建一个新线程(使用thread.start())并将链接传递给我的程序,在启动新线程之前,我等待线程完成(使用thread.join)(同时执行会导致一些问题,我这样做是为了防止意外的线程结束停止其他链接的执行) 问题是,有时候JSoup抛出一个SocketTimeoutException(我应该捕获它),这会使我的程序冻结。我不知道为什么执行会停止,甚至被t

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

问题是,有时候JSoup抛出一个SocketTimeoutException(我应该捕获它),这会使我的程序冻结。我不知道为什么执行会停止,甚至被
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();
    }
}
在我的过程中:

// 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";
}
这很烦人,因为这个过程很长,我让它运行了一夜,今天发现我的程序在第54个链接冻结了。^^^提前谢谢

编辑-更新

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

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

            }
    });
    i++;                                            //DEBUG
    }
ex.shutdown();

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

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

如果需要多线程程序,请考虑使用

如果我们遇到您的问题,我宁愿完全按照下面的方式更改此程序,因为您正在连接部件上捕获异常,但这并不保证您的异常已在该部件上引发

new Runnable(){

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

            }
        }.run();

我没有在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();

我不知道ExecutionService的存在。虽然我不知道它是如何工作的,但它似乎很有希望,因为我可以与我的JPanel交互,所以我宁愿尝试使用此选项。因此我会在for循环之外创建一个新的executor服务(
ExecutionService ex=Executors.newSingleThreadExecutor();
)然后在我的循环中写:
ex.execute(new Runnable(){[…]);
在我的循环之后,用
ex.shutdown()
结束,正确吗?并添加一个ex.waitForTermination()`或者某些提交的任务可能无法运行。此外,如果您的工作人员实现了Callable而不是Runnable,则可以轻松返回操作的Resultl。是的,这是正确的,如果您想使其在后台工作。Q.仅启动线程以立即
join()
A.无。@EJP如果我只使用一个线程在600个链接上执行我的进程,只有一个线程中断就会停止整个进程(我已经遇到了这个问题),如果我不一个接一个地执行每个进程,我就会遇到其他问题(特别是一些文件处理).我理解你的想法,但这是我用我的知识找到的解决问题的唯一方法。:)while loop是一个相当丑陋的解决方案。。。只需调用executerService.awaitTermination(),这是肯定的,但是executerService.awaitTermination();只有在主线程上没有其他操作时才有用。如果它是一个基于UI的程序,他可能正在更新状态栏等@Victor它与whil循环配合得很好,也许最好使用
awaitTermination()
,但是它有两个参数,因此该方法需要:
executorService.awaitTermination(长,时间单位)
,那么,在我的例子中,我最好传递什么作为参数呢?executorService.awaitTermination()不是while循环的替代品。while循环正在检查是否为Runnable();已经完成。executorService.awaitTermination()告诉executorService不再接受任何可运行程序,并等待正在运行的线程退出。@GregKing,可以,但在本例中,主线程仍处于休眠状态。关于await():例如(1000,TimeUnit.milisons)``、(5,TimeUnit.Minutes)`,等等