0

I've made a code executing 4 threads that would add 5000 integers each to a list. At the end of the execution, I'm supposed to have 4 * 5000 elements in my list. But I end up with only 1190 (the number may change)

Here the code :

import java.util.ArrayList;
import java.util.List;

public class ConcurentList {
    public static void main(String[] args) throws InterruptedException {
        int range = 5000;
        int nbThreads = 4;

        List<Integer> integers = new ArrayList<>();
        ThreadSafeArrayList<Integer> integerThreadSafeArrayList = new ThreadSafeArrayList<>(integers);
        Thread[] arrayOfThread = new Thread[nbThreads];
        for (int i = 0; i < nbThreads; i++)
        {
            arrayOfThread[i] = new Thread(() -> {
                for (int j = 0; j < range; j++) {
                    integerThreadSafeArrayList.add(1);
                }
            });
            arrayOfThread[i].start();
            System.out.println("Le thread " + i + " ended.");
        }
        System.out.println("Size of the list " + integerThreadSafeArrayList.getSize());
    }
}

And ThreadSafeArrayList :

import java.util.List;

public class ThreadSafeArrayList<T> {
    private List<T> list;
    private final Object lock = new Object();

    public ThreadSafeArrayList(List<T> list) {
        this.list = list;
    }

    public boolean add(T element) {
        boolean add;
        synchronized (lock) {
            add = list.add(element);
        }
        return add;
    }

    public int getSize() {
        return list.size();
    }
}

I understand that arraylist isn't thread safe and therefor the predict the behaviour of the execution but since I used a synchronized on private final lock I expected to obtain the normal behaviour.

What am I missing ?

3 Answers 3

1

That is because, when this gets executed,

System.out.println("Size of the list " + integerThreadSafeArrayList.getSize());

the other threads are still running and doing the work that you have asked them to do.

To see the actual result, add this line just before the last statement.

TimeUnit.SECONDS.sleep(5);

The output I can see now is:

Le thread 0 ended.
Le thread 1 ended.
Le thread 2 ended.
Le thread 3 ended.
Size of the list 20000
Sign up to request clarification or add additional context in comments.

1 Comment

I'm so dumb... Ty
1

There are 2 issues:

  1. You need to join started threads to let them finish their work before method main ends.

    for (Thread thread : arrayOfThread) {
        thread.join();
    }
    
  2. Method getSize is not thread safe, thus you need to use synchronization:

    public int getSize() {
        synchronized (lock) {
            return list.size();
        }
    }
    

Comments

0

wait result

for (int i = 0; i < nbThreads; i++) {
    arrayOfThread[i].join();
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.