Very fickle output in multithreaded application along with Exception

Asked

Viewed 24 times

0

I’m seeing threads now and doing some experiments. It’s a simple test, I want to print on the console ten times the name of each thread by inserting into the same object of type List in a synchronized way (one ends the other begins).

The problem is that my program keeps giving Exception ArrayIndexOutOfBoundsException with a very fickle output. One hour prints the threads names correctly, and in the end Exception, another neither prints the names on the screen.

Follows the code:

import java.util.List;

public class ThreadsTeste {


    public static void main(String[] args) {

        TarefaAdicionaString obj = new TarefaAdicionaString();
        List<String> lista = obj.getLista();


        Thread thread1 = new Thread(obj, "Thread - 1");
        Thread thread2 = new Thread(obj, "Thread - 2");

        thread1.start();
        thread2.start();

        for(int i=0; i < 100; i++){
            System.out.println(lista.get(i));
        }



    }

}
import java.util.List;
import java.util.Vector;


public class TarefaAdicionaString implements Runnable{

    public List<String> lista = new Vector<String>();

    public List<String> getLista(){
        return this.lista;
    }

    @Override
    public void run() {
        synchronized(this){
            for(int i=0; i < 10; i ++){
                this.lista.add(Thread.currentThread().getName());              
            }
        }
    }

}

1 answer

3


The operation System.out.println is quite slow. You make a sequence of 100 instructions System.out.println(lista.get(i)); in the main thread, and therefore outside the thread1 and of thread2. Thread 1 will add 10 elements to the list and thread 2 will add another 10. The result is that there will be 20 elements. Soon, the main thread will fatally get a ArrayIndexOutOfBoundsException when i is equal to 20.

The order of the inserts is indeterminate in relation to the System.out.println, soon it is possible that you have a ArrayIndexOutOfBoundsException before the 20 items are inserted into the list. In fact, since the main thread probably arrives in the for well before any of the auxiliary threads start, the most likely result is that it will ArrayIndexOutOfBoundsException right on the face at position 0, which is what happened to me with all the tests I made of your code without modifying it.

The order in which threads will be started is indeterminate. Note that like both threads thread1 and thread2 synchronize in the same object inside the run(), you will first have all 10 elements of one of these threads in the list and then the 10 elements of the other thread. But they will never appear intertwined/alternate.

All the tests I did adding one Thread.sleep(10); before the for of the main thread had the behavior of first displaying the 10 items of the thread1, then the 10 items from thread2 and then the ArrayIndexOutOfBoundsException.

The fact that sometimes it crashes is an indication that a deadlock occurs. However, looking at the code, I don’t see how a deadlock is possible and I couldn’t simulate any by just making minimal changes to your code.

  • And what would be a safer option for execption not to appear?

  • 1

    @Lucasmarinzeck The code you gave is a very "artifical" problem, so it’s hard to say what the best approach would be to be naturally explored in your real problem. However, it is most likely that the best solution is to exchange the for (int i=0; i < 100; i++) { System.out.println(lista.get(i)); } for for (int i=0; i < lista.size(); i++) { System.out.println(lista.get(i)); } or better still, by for (String x : lista) { System.out.println(x); }.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.