Java 为什么SocketTimeoutException使我的程序冻结?
我给我的程序提供了600多个链接,存储在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
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)`,等等