2

我使用 JSoup(以及其他)为我的程序提供了超过 600 个链接,ArrayList以获取网页的标题。对于每个链接(使用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();

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

4

2 回答 2

1

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

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

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

new Runnable(){

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

            }
        }.run();
于 2015-04-29T08:08:36.700 回答
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();
于 2015-04-29T08:44:51.067 回答