2

ArrayListJSoup (とりわけ) を使用して、Web ページのタイトルを取得するためにストックされた 600 以上のリンクをプログラムに提供します。リンクごとに ( 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 は、スレッドを作成して start()-join() を作成する代わりに、ExecutorService を使用することを提案したので、次のことを試しました。

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

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 に答える
1

リンクごとに新しいスレッドを開くのは、非常に悪いオプションです。

マルチスレッド プログラムが必要な場合は、ExecutionServiceの使用を検討してください。

問題が発生した場合は、このプログラムを以下のように正確に変更したいと思います。なぜなら、結合部分で例外をキャッチしていて、この部分で例外がスローされたことを保証するものではないからです..

new Runnable(){

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

            }
        }.run();
于 2015-04-29T08:08:36.700 に答える