garg10may garg10may - 9 months ago 30
Java Question

Not able to break classic lazy initialization Singleton

I am trying to create various singleton patterns and check for breaks using millions of threads. I was hoping this would lead me to implement Bill Pugh ultimately. But I am not even able to break the classical one.

Singleton: Previously tried a million threads, all were having same hashcode. So I made it sleep for 10 sec so that both threads are sure to enter null check condition but all in frustration.

package demo2;

public class Singleton {

private static Singleton soleInstance = null;

private Singleton() throws InterruptedException {

}

public static Singleton getInstance() throws InterruptedException {

if (soleInstance == null) {

Thread.sleep(10000);

soleInstance = new Singleton();

}

return soleInstance;

}

}


Test Class:

package demo2;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

class Test {

public int makeSingleton() throws InterruptedException {

Singleton s = Singleton.getInstance();

return s.hashCode();

}

public static void main(String[] args) throws InterruptedException, ExecutionException {

Test t = new Test();

ExecutorService executor = Executors.newFixedThreadPool(2);

List<Integer> list = new ArrayList<>();

for (int i = 0; i < 2; i++) {

Future<Integer> future = executor.submit(new Callable<Integer>() {

public Integer call() throws InterruptedException {

return t.makeSingleton();
}
});

list.add(future.get());
}

executor.shutdown();

List<Integer> list2 = list.stream().distinct().collect(Collectors.toList());

System.out.println(list2);

}
}


How the hell do I break it?

Answer Source

Below mentioned code will work.

Change your code. May be you are calling get inside method only and it's waiting to get results & loop count won't increment.

ExecutorService executor = Executors.newFixedThreadPool(2);

        List<Future<Integer>> list = new ArrayList<Future<Integer>>();

        for (int i = 0; i < 5; i++) {

            Future<Integer> future = executor.submit(new Callable<Integer>() {

                public Integer call() throws InterruptedException {

                    return Singleton.getInstance().hashCode();
                }
            });

            list.add(future);
        }

        executor.shutdown();

        Set<Integer> output = new HashSet<Integer>(); 
        for(Future<Integer> future : list){
            output.add(future.get());
        }

        System.out.println(output);