Search code examples
javamultithreadingfreezeexecutorservicesocket-timeout-exception

Why SocketTimeoutException makes my program freeze?


I give my program over than 600 links, stocked in an ArrayList to get the title of the webpage, using JSoup (among others). For every link (using a for loop), I create a new thread (using thread.start()) and pass the link through my program, I wait for my thread to finish (with thread.join) before launching a new thread (simultaneous execution would cause some problems, I did that to prevent an unexpected thread end to stop the execution for the other links).

The problem is that sometimes, JSoup throws a SocketTimeoutException (which I'm supposed to catch), which makes my program freeze. I don't know why the execution stops even surrounded with a try/catch.

Here's a piece of my code, maybe that could help you understand :

// 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();
    }
}

And in my process :

// 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";
}

It's annoying because the process is veeery long, I let it run for the night, and find today that my program froze at the 54th link. ^^' Thank you in advance !

EDIT - UPDATE

SercanOzdemir suggested me to use ExecutorService, instead of creating threads and making start()-join(), so I tried :

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();

But it prints only my debug links. Any idea of why it doesn't run my process ?


Solution

  • I've not tried this with jsoup but it is a simple way of creating threads to do a task and monitoring their status.

        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();
    

    The code in your updated question won't work because you are creating the service and instantly overwriting it without waiting for it to complete.

    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();