Reputation: 6179
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?
Upvotes: 0
Views: 153
Reputation: 106
Please check this:
/**
* <p>
* If you would like to immediately block waiting
* for a task, you can use constructions of the form
* {@code result = exec.submit(aCallable).get();}
*/
<T> Future<T> submit(Callable<T> task);
If you use
Future<Integer> future = executor.submit(new Callable<Integer>()
it will block you thread till the result return.
If you want to break the classical singleton pattern, try this code
public class BreakSingleton {
public MySingleton makeSingleton() throws InterruptedException {
MySingleton s = MySingleton.getInstance();
return s;
}
public static void main(String[] args) throws Exception {
BreakSingleton t = new BreakSingleton();
ExecutorService executor = Executors.newFixedThreadPool(2);
final List<MySingleton> list = new ArrayList<>();
System.out.println(Thread.currentThread().getName());
for (int i = 0; i < 2; i++) {
executor.submit(new Callable<MySingleton>() {
public MySingleton call() throws InterruptedException {
MySingleton mySingleton = t.makeSingleton();
list.add(mySingleton);
return mySingleton;
}
});
}
executor.shutdown();
Thread.sleep(5000);
System.out.println(list);
}
}
class MySingleton {
private static MySingleton instance = null;
private MySingleton() {
}
public static MySingleton getInstance() throws InterruptedException {
System.out.println(Thread.currentThread().getName());
if (instance == null) {
Thread.sleep(3000);
System.out.println(Thread.currentThread().getName());
instance = new MySingleton();
}
return instance;
}
}
Upvotes: 1
Reputation: 2080
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);
Upvotes: 2