为什么 SocketTimeoutException 使我的程序冻结?
Why SocketTimeoutException makes my program freeze?
我给了我的程序超过 600 links,存储在一个 ArrayList
中以获得网页的标题,使用 JSoup(以及其他)。对于每个 link(使用 for 循环),我创建一个新线程(使用 thread.start()
)并通过我的程序传递 link,我在启动新线程之前等待我的线程完成(thread.join
)(同时执行会导致一些问题,我这样做是为了防止意外的线程结束以停止其他 links 的执行) .
问题是有时,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";
}
很烦人,因为过程很长,我让它运行过夜,今天发现我的程序卡在第54link。 ^^' 提前谢谢你!
编辑 - 更新
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();
但它只打印我的调试 links。知道为什么它不 运行 我的流程吗?
为每个 link 打开一个新线程是一个非常糟糕的选择。
如果您想要多线程程序,请考虑使用ExecutionService。
如果我们遇到您的问题,我宁愿完全按照下面的方式更改此程序,因为您在连接部分捕获异常并且不能保证您的异常已在此部分抛出..
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();
我给了我的程序超过 600 links,存储在一个 ArrayList
中以获得网页的标题,使用 JSoup(以及其他)。对于每个 link(使用 for 循环),我创建一个新线程(使用 thread.start()
)并通过我的程序传递 link,我在启动新线程之前等待我的线程完成(thread.join
)(同时执行会导致一些问题,我这样做是为了防止意外的线程结束以停止其他 links 的执行) .
问题是有时,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";
}
很烦人,因为过程很长,我让它运行过夜,今天发现我的程序卡在第54link。 ^^' 提前谢谢你!
编辑 - 更新
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();
但它只打印我的调试 links。知道为什么它不 运行 我的流程吗?
为每个 link 打开一个新线程是一个非常糟糕的选择。
如果您想要多线程程序,请考虑使用ExecutionService。
如果我们遇到您的问题,我宁愿完全按照下面的方式更改此程序,因为您在连接部分捕获异常并且不能保证您的异常已在此部分抛出..
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();