Java Multithread with shared List - java

I need a little help with java multithread. I have this class:
public class EdgeServer{
private static final int ServidorBordaID = 9;
private static final String urlLogin = "http://localhost/exehdager-teste/index.php/ci_login/logar";
private static final String insertSensorURI = "http://localhost/exehdager-teste/index.php/cadastros/ci_sensor/gravaSensor";
private static final String insertGatewayURI = "http://localhost/exehdager-teste/index.php/cadastros/ci_gateway/gravaGateway";
private static ArrayList<Gateway> gatewaysCadastrados = new ArrayList<>();
public static void main(String[] args) {
// Start a user thread that runs the UPnP stack
Thread clientThread = new Thread(new Descoberta());
clientThread.setDaemon(false);
clientThread.start();
Thread publicationThread = new Thread(new Publication());
publicationThread.setDaemon(false);
publicationThread.start();
}
}
The thread Descoberta will add new itens to gatewaysCadastrados list on demand. and the Publication thread will read this list and execute an action for each object on list.
I just need to know how to share and pass this var to threads. Will I need to build a semaphore to do this?

Here is the sample code where you can share list between two threads and you need to use wait and notify for semaphore.
public class Descoberta extends Thread {
private final ArrayList<Gateway> a = new ArrayList<>();
public Descoberta( ArrayList<Gateway> a) {
this.a = a;
}
#Override
public void run() {
synchronized (a) {
while(true){ // your condition
a.wait();
}
a.notify();
}
}
}
public class Publication extends Thread {
private final ArrayList<Gateway> b = new ArrayList<>();
public Publication(ArrayList<Gateway> b) {
this.b = b;
}
#Override
public void run() {
synchronized (b) {
while(true){ // your condition
b.wait();
}
b.notify();
}
}
}
public class EdgeServer {
public static void main(String args[]) {
private final ArrayList<Gateway> gatewaysCadastrados = new ArrayList<>();
Thread clientThread = new Descoberta(gatewaysCadastrados);
Thread publicationThread = new Publication(gatewaysCadastrados);
clientThread.start();
publicationThread.start();
}
}

A simple way it to pass the shared object as a constructor parameter to the relevant runnables; e.g.
Thread clientThread = new Thread(new Descoberta(gateways));
...
Thread publicationThread = new Thread(new Publication(gateways));
Obviously, the respective Runnable constructors need to save the parameters so that their run() methods can find them.
There are various other ways:
If the runnables are inner classes within the same outer class instance, they can access shared objects in outer class.
If the shared state is stored in static variables, then the runnables can access them via static getters, etcetera. (NOTE: this is most likely bad design ...)
And as #Fidor points out, if two or more threads are going to share a common (mutable) data structure, then they need to synchronize their read and write operations on the data structure. If you neglect this, your application is liable to have the kind of insidious bugs that are hard to reproduce and hard to track down.

Related

how to get the acquired index from Semaphore

I have an array of int with size 4, only one thread can access an array cell at a time.
I thought about using Semaphore but I don't know how or if there is a way to get the acquired index
I build a code example to explain butter:
public class Temp {
private ExecutorService executeService;
private Semaphore semaphore;
private int[] syncArray; // only one thread can access an array cell at the same time
public Temp() {
syncArray = new int[]{1,2,3,4};
executeService = Executors.newFixedThreadPool(10);
semaphore = new Semaphore(syncArray.length, true);
for(int i = 0;i < 100; i++) {
executeService.submit(new Runnable() {
#Override
public void run() {
semaphore.acquire();
// here I want to access one of the array cell
// dose not matter witch one as long as no other thread is currently use it
int syncArrayIndex = semaphore.getAcquiredIndex(); // is something like this possible?
syncArray[syncArrayIndex] += ...;
semaphore.release();
}
});
}
}
}
Edit:
this is a piece of code that looks closer the my real problem:
public class Temp {
private ExecutorService executeService;
private Semaphore semaphore;
private static ChromeDriver driver;
public Temp() {
executeService = Executors.newFixedThreadPool(10);
}
public Future<WikiPage> getWikiPage(String url) {
executeService.submit(new PageRequest(url) {
});
}
private static class PageRequest implements Callable<WikiPage> {
String url;
public PageRequest(String url) {
this.url = url;
}
#Override
public WikiPage call() throws Exception {
String html = "";
synchronized (driver) {
html = ...// get the wiki page, this part takes a log time
};
WikiPage ret = ...// parse the data to the WikiPage class
// this part takes less time but depend on the sync block above
return ret;
}
}
}
#Kayaman I'm not sure I understand your comment, the problem is that I return a future. Do you have a any suggestions on how to improve my code to run faster?
No, semaphore isn't useful here. It only knows about how many permits it has, there are no "indices" in a semaphore.
You can use AtomicIntegerArray instead, although if you explain your root problem, there may be a more suitable class to use.

Java Multithreading example

I'm a Java student and this is my attempt of implementing a StackExchange (there's a pusher thread and a popper thread, a single stack resource and two controlling Threads for the stack content and time passing).
I was hoping if someone could comment my code for improvements or errors\bad practices, even if the code seems to work.
The main reason of this program was to figure out how to control resource access in a multithreading environment.
I have concerns about the use of the ScheduledThreadPoolExecutor rather than locking(the stack), and my usage of synchronized in the StackExchange class methods(for accessing the stack), I would like to spawn free threads working on a dynamically locked resource. Any advice?
NB:"Format of magic numbers and syso's may be awful for testing porpuses
code here:
package examples;
import java.util.Random;
import java.util.Stack;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import javax.swing.JOptionPane;
public class StackExchange {
/*
* Two Threads playing with a stack, a timer and a controller for the stack that permits to exit
* */
public class Popper implements Runnable
{
StackExchange sEx;
public Popper(StackExchange sex)
{
this.sEx=sex;
}
#Override
public void run() {
System.out.println("Popper: popping!\t"+sEx.getPeek());
sEx.callTheStack(this, null);
}
}
public class Pusher implements Runnable
{
StackExchange sEx;
public Pusher(StackExchange sex)
{
sEx=sex;
}
#Override
public void run() {
System.out.println("Pusher: pushing!\t");
sEx.callTheStack(this, "Hi!");
}
}
public class StackController implements Runnable
{
private Stack<String> theStack;
public int waiting=5;
public StackController(Stack<String> theStack, String name) {
this.theStack = theStack;
Thread.currentThread().setName(name);
}
#Override
public void run()
{
Random rand = new Random();
waiting = rand.nextInt(10);
StringBuilder buffer = new StringBuilder();
int i=0;
for(String string: theStack)
{
buffer.append(string+"\n");
i++;
}
buffer.append("\nFound "+i+" elements\nIWillWait4:\t"+waiting);
System.out.println("\t\t\t\t\t\t\t\t"+Thread.currentThread().getName().toString()+" Says:" + buffer.toString());
if(i>1)
{
System.out.println("ERRER");
System.exit(0);
}
if(i==1 && JOptionPane.showConfirmDialog(null, "found 1 element\nWannaStop?")==0)
System.exit(0);
}
}
public class Timer implements Runnable{
#Override
public void run() {
StackExchange.time++;
System.out.println("Time Passed:\t"+StackExchange.time+" seconds");
}
}
/*
* implementation of the StackExchange class
* */
private Popper popper;
private Pusher pusher;
private StackController stackController;
private StackController secondSC;
private Timer timer;
static int time=0;
private Stack<String> stack;
public StackExchange()
{
timer = new Timer();
stack = new Stack<String>();
pusher = new Pusher(this);
popper = new Popper(this);
stackController = new StackController(this.getStack(), "FirstStackController");
}
public static void main(String[] args) {
StackExchange sex = new StackExchange();
sex.start();
System.out.println("Num of Threads:"+Thread.activeCount());
}
public void start()
{
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(5);
exec.scheduleAtFixedRate(timer, 0, 1, TimeUnit.SECONDS);
exec.scheduleAtFixedRate(pusher, 0, 2, TimeUnit.SECONDS);
exec.scheduleAtFixedRate(popper, 1, 2, TimeUnit.SECONDS);
exec.scheduleAtFixedRate(stackController, 0, stackController.waiting, TimeUnit.SECONDS);
}
public Stack<String >getStack()
{
return this.stack;
}
public void callTheStack(Object caller, String pushedString)
{
synchronized(this)
{
if(caller instanceof Popper)
stack.pop();
else if(caller instanceof Pusher)
stack.push(pushedString);
}
}
public String getPeek()
{
synchronized(this)
{
return stack.peek();
}
}
}
Things that might help:
Don't use java.util.Stack.
A more complete and consistent set of LIFO stack operations is
provided by the Deque interface and its implementations, which should
be used in preference to this class.
http://docs.oracle.com/javase/8/docs/api/java/util/Stack.html
Your nested subclasses of StackExchange are all inner classes so
that means they already have a reference to the containing
StackExchange instance
and its member stack instance, which should be final.
So don't pass them as parameters. This simplifies logic, maintenance,
and GC.
caller instanceof Popper this type of reflection is utterly
unnecessary and breaks object orientation.
You know that Object is too broad a type for callTheStack (weak
name). In fact, you know that the object will be a Runnable, but
more importantly, the Runnable should know what to do already.
Synchronization should be kept minimal to just the critical section that shares data and no more, shown below using the synchronized keyword
or to just the memory boundary, shown below using the volatile keyword
and member variables of a containing class are a great way to share data between threads within the class.
Example
public class StackExchange {
private final Deque<String> stack = new ArrayDeque<>();
private volatile boolean running;
private void consume(String item) {
// ...
}
private String obtain() {
// ...
}
private boolean getPermission() {
// ...
}
// getters, setters, ...
private final Runnable consumer = new Runnable() {
#Override
public void run() {
while (running) {
final String popped;
synchronized(stack) {
popped = stack.pollFirst();
}
consume(popped);
}
}
};
private final Runnable producer = new Runnable() {
#Override
public void run() {
while (running) {
final String pushing = obtain();
synchronized(stack) {
stack.offerFirst(pushing);
}
}
}
};
public static void main(String ... args) {
StackExchange exchange = new StackExchange();
exchange.setRunning(true);
new Thread(exchange.getConsumer()).start();
new Thread(exchange.getProducer()).start();
do {
} while (exchange.getPermission());
exchange.setRunning(false);
}
}
It's a good idea to declare member variables prior to member methods.
I put the Runnable code in anonymous classes to leave the code at the very edge of using lambdas.
The idea behind consume, obtain, and getPermission is to hint at how the code would interact with the business logic that doesn't know about threading. These could be implemented as callbacks or abstract methods.
One good thing about Deque is that it can easily be set up for a FIFO queue.
Just for fun, convert those Runnable instances into lambdas, and make the StackExchange class generic.
Hot question: what other subtypes of Deque<E> might suit, and what advantages or disadvantages would they have? What code changes might need to happen to accommodate them?

Access thread variable that changes from main thread

So, I am new to threads, and I'm still learning how everything works. So, I couldn't find an answer that would provide an explanation for my problem (to my level of understanding).
I have a Runnable class that looks like so:
public class Request implements Runnable {
private Boolean ok = true;
public synchronized void setOk(Boolean ok) {
this.ok = ok;
}
public synchronized Boolean getOk() {
return ok;
}
private synchronized void foo() {
//if something happens
setOk(false);
}
#Override
public void run() {
while (true)
foo();
}
}
And then I have another class that does the following:
private static Request request;
private static void spawnThreads() {
ExecutorService e = new Executors.newFixedThreadPool(4);
request = new Request();
e.execute(request);
}
public static void main(String[] args) {
spawnThreads();
while (true) {
System.out.println(request.getOk());
if (!request.getOk())
request.setOk(true);
TimeUnit.SECONDS.sleep(10);
}
}
I need that if in the main thread, that getOk() returns false, do something and set it to true. Viceversa, set it to false in the thread (which I need to keep on going, no matter what the value of ok is at any given time).
As this code is, I can't get the value of request.getOk() in the main thread. If I remove the synchronized words from the getter and setter, I can access the value in the main thread until a point in time when it is changed by the thread, and never again.
Also, the executor is used because I would create multiple Request objects, and waiting for it to shutdown before accessing the variable would contradict my reason for doing this, as I would need all the threads to keep running.
That thread is making http requests to a server (that randomly times out, denies response, etc) and is used to retrieve some information. The ok variable is there to take a note when the thread acquires an ok response and some information from the server.
How do I solve it so that the thread can update that variable, but the main thread to be able to retrieve it whenever needed, no matter if it was changed by the thread in the meanwhile or not.
Would changing my Runnable to a Callable help? If yes, how?
Your example still leaves some holes in the thread-safety. Like mentioned by #Radiodef using AtomicBoolean can relieve you of most of the synchronisation if used properly.
Using your example, this is a thread safe Request class that accepts a message, like an answer to a http request.
public final class Request implements Runnable {
private final AtomicBoolean ok = new AtomicBoolean(false);
// volatile variables promote reference changes through all threads
private volatile String msg;
private boolean setMessage(String responseMessage) {
if (this.ok.compareAndSet(false, true)) {
this.msg = msg;
return true;
}
return false;
}
public boolean hasMessage() {
// *pure* getters don't need synchronisation!
return this.ok.get();
}
public String getMessageAndReset() {
// make a copy before resetting the OK
String msgCopy = this.msg;
this.ok.compareAndSet(true, false);
return msgCopy;
}
public void run() {
final Random rand = new Random();
try {
while(true) {
// sleep at random max 5 seconds
// (simulate unpredictable network)
TimeUnit.SECONDS.sleep(rand.nextInt(5));
while(!setMessage("Incoming message")) {
// busy waiting ... waits until the current value has
// been retrieved by the main thread
Thread.sleep(100);
}
}
} catch (Exception e) {
System.out.println(e);
}
}
}
And your main class:
public final class MainClazz implements Runnable {
private final ExecutorService exec;
private final Request request;
public void MainClazz() {
this.exec = new Executors.newFixedThreadPool(4);
this.request = new Request();
this.exec.execute(request);
}
public void run() {
while (true) {
if (request.hasMessage()) {
System.out.println(request.getMessageAndReset());
}
TimeUnit.SECONDS.sleep(10);
}
public static void main(String[] args) {
MainClazz main = new MainClazz();
main.run();
}
}
In this implementation, the Request class only holds a single value at a time. Depending the amount of data you expect you might want to think about using a buffer.
Also, like many others have mentioned, don't use while (true)! Get a synchronisation object from the java concurrent package!
More light reading on the AtomicBoolean object.

A Thread as an object Java

I want a collection of objects that inherit from Thread; each object running in it's own thread.
I tried extends Thread and called super() thinking that'd ensure a new thread is created; but no... only main is the running thread :(
Everyone tells me, "implement Runnable put the code you want in run() and put it in a thread-object".
I can't do this because of 2-reasons:
My collection-elements aren't of-type Thread and if I polymorph I'll have to change all it's dependencies.
run() can't contain an entire class... right?
So I want to know firstly, if what I want to do is even possible and
secondly, if so, how to do it?
super() just calls the parent constructor (in your case the default Thread constructor). The method to actually start the new thread is start(). As others have said, it's poor design to extend Thread.
Yes, you can create a class that implements Runnable
class MySpecialThread implements Runnable {
public void run() {
// Do something
}
}
and you can start it in a new thread like this:
Thread t = new Thread(new MySpecialThread());
// Add it to a collection, track it etc.
t.start(); // starts the new thread
1- You can use collections of Runnables OR collections of Threads using the example below.
MySpecialThread m = new MySpecialThread();
List<Runnable> runnables = new ArrayList<Runnable>();
runnables.add(m);
List<Thread> threads = new ArrayList<Thread>();
threads.add(new Thread(m));
2- A method can't contain a class, but the above example MySpecialThread is a class that behaves like any other class. You can write a constructor, add methods and fields, etc.
I recommend to use ExecutorService
Let's have a sample code on usage of ExecutorService
import java.util.*;
import java.util.concurrent.*;
public class ExecutorServiceDemo {
public static void main(String args[]){
ExecutorService executor = Executors.newFixedThreadPool(10);
List<Future<Integer>> list = new ArrayList<Future<Integer>>();
for(int i=0; i< 10; i++){
CallableTask callable = new CallableTask(i+1);
Future<Integer> future = executor.submit(callable);
list.add(future);
}
for(Future<Integer> fut : list){
try {
System.out.println(fut.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
executor.shutdown();
}
}
class CallableTask implements Callable<Integer>{
private int id = 0;
public CallableTask(int id){
this.id = id;
}
public Integer call(){
// Add your business logic
return Integer.valueOf(id);
}
}
output:
1
2
3
4
5
6
7
8
9
10
If you want to use Thread instead of ExecutorService, below code should work for you.
import java.util.*;
class MyRunnable implements Runnable{
private int id = 0;
public MyRunnable(int id){
this.id = id;
}
public void run(){
// Add your business logic
System.out.println("ID:"+id);
}
}
public class RunnableList{
public static void main(String args[]){
List<Thread> list = new ArrayList<Thread>();
for ( int i=0; i<10; i++){
Thread t = new Thread(new MyRunnable(i+1));
list.add(t);
t.start();
}
}
}

Thread-safe multiton pattern

Inspired by a comment to an given answer I tried to create a thread-safe implementation of the multiton pattern, which relies on unique keys and performs locks on them (I have the idea from JB Nizet's answer on this question).
Question
Is the implementation I provided viable?
I'm not interested in whether Multiton (or Singleton) are in general good patterns, it would result in a discussion. I just want a clean and working implementation.
Contras:
You have to know how many instances you want to create at compile time .
Pros
No lock on whole class, or whole map. Concurrent calls to getInstanceare possible.
Getting instances via key object, and not just unbounded int or String, so you can be sure to get an non-null instance after the method call.
Thread-safe (at least that's my impression).
public class Multiton
{
private static final Map<Enum<?>, Multiton> instances = new HashMap<Enum<?>, Multiton>();
private Multiton() {System.out.println("Created instance."); }
/* Can be called concurrently, since it only synchronizes on id */
public static <KEY extends Enum<?> & MultitionKey> Multiton getInstance(KEY id)
{
synchronized (id)
{
if (instances.get(id) == null)
instances.put(id, new Multiton());
}
System.out.println("Retrieved instance.");
return instances.get(id);
}
public interface MultitionKey { /* */ }
public static void main(String[] args) throws InterruptedException
{
//getInstance(Keys.KEY_1);
getInstance(OtherKeys.KEY_A);
Runnable r = new Runnable() {
#Override
public void run() { getInstance(Keys.KEY_1); }
};
int size = 100;
List<Thread> threads = new ArrayList<Thread>();
for (int i = 0; i < size; i++)
threads.add(new Thread(r));
for (Thread t : threads)
t.start();
for (Thread t : threads)
t.join();
}
enum Keys implements MultitionKey
{
KEY_1;
/* define more keys */
}
enum OtherKeys implements MultitionKey
{
KEY_A;
/* define more keys */
}
}
I tried to prevent the resizing of the map and the misuse of the enums I sychronize on.
It's more of a proof of concept, before I can get it over with! :)
public class Multiton
{
private static final Map<MultitionKey, Multiton> instances = new HashMap<MultitionKey, Multiton>((int) (Key.values().length/0.75f) + 1);
private static final Map<Key, MultitionKey> keyMap;
static
{
Map<Key, MultitionKey> map = new HashMap<Key, MultitionKey>();
map.put(Key.KEY_1, Keys.KEY_1);
map.put(Key.KEY_2, OtherKeys.KEY_A);
keyMap = Collections.unmodifiableMap(map);
}
public enum Key {
KEY_1, KEY_2;
}
private Multiton() {System.out.println("Created instance."); }
/* Can be called concurrently, since it only synchronizes on KEY */
public static <KEY extends Enum<?> & MultitionKey> Multiton getInstance(Key id)
{
#SuppressWarnings ("unchecked")
KEY key = (KEY) keyMap.get(id);
synchronized (keyMap.get(id))
{
if (instances.get(key) == null)
instances.put(key, new Multiton());
}
System.out.println("Retrieved instance.");
return instances.get(key);
}
private interface MultitionKey { /* */ }
private enum Keys implements MultitionKey
{
KEY_1;
/* define more keys */
}
private enum OtherKeys implements MultitionKey
{
KEY_A;
/* define more keys */
}
}
It is absolutely not thread-safe. Here is a simple example of the many, many things that could go wrong.
Thread A is trying to put at key id1. Thread B is resizing the buckets table due to a put at id2. Because these have different synchronization monitors, they're off to the races in parallel.
Thread A Thread B
-------- --------
b = key.hash % map.buckets.size
copy map.buckets reference to local var
set map.buckets = new Bucket[newSize]
insert keys from old buckets into new buckets
insert into map.buckets[b]
In this example, let's say Thread A saw the map.buckets = new Bucket[newSize] modification. It's not guaranteed to (since there's no happens-before edge), but it may. In that case, it'll be inserting the (key, value) pair into the wrong bucket. Nobody will ever find it.
As a slight variant, if Thread A copied the map.buckets reference to a local var and did all its work on that, then it'd be inserting into the right bucket, but the wrong buckets table; it wouldn't be inserting into the new one that Thread B is about to install as the table for everyone to see. If the next operation on key 1 happens to see the new table (again, not guaranteed to but it may), then it won't see Thread A's actions because they were done on a long-forgotten buckets array.
I'd say not viable.
Synchronizing on the id parameter is fraught with dangers - what if they use this enum for another synchronization mechanism? And of course HashMap is not concurrent as the comments have pointed out.
To demonstrate - try this:
Runnable r = new Runnable() {
#Override
public void run() {
// Added to demonstrate the problem.
synchronized(Keys.KEY_1) {
getInstance(Keys.KEY_1);
}
}
};
Here's an implementation that uses atomics instead of synchronization and therefore should be more efficient. It is much more complicated than yours but handling all of the edge cases in a Miltiton IS complicated.
public class Multiton {
// The static instances.
private static final AtomicReferenceArray<Multiton> instances = new AtomicReferenceArray<>(1000);
// Ready for use - set to false while initialising.
private final AtomicBoolean ready = new AtomicBoolean();
// Everyone who is waiting for me to initialise.
private final Queue<Thread> waiters = new ConcurrentLinkedQueue<>();
// For logging (and a bit of linguistic fun).
private final int forInstance;
// We need a simple constructor.
private Multiton(int forInstance) {
this.forInstance = forInstance;
log(forInstance, "New");
}
// The expensive initialiser.
public void init() throws InterruptedException {
log(forInstance, "Init");
// ... presumably heavy stuff.
Thread.sleep(1000);
// We are now ready.
ready();
}
private void ready() {
log(forInstance, "Ready");
// I am now ready.
ready.getAndSet(true);
// Unpark everyone waiting for me.
for (Thread t : waiters) {
LockSupport.unpark(t);
}
}
// Get the instance for that one.
public static Multiton getInstance(int which) throws InterruptedException {
// One there already?
Multiton it = instances.get(which);
if (it == null) {
// Lazy make.
Multiton newIt = new Multiton(which);
// Successful put?
if (instances.compareAndSet(which, null, newIt)) {
// Yes!
it = newIt;
// Initialise it.
it.init();
} else {
// One appeared as if by magic (another thread got there first).
it = instances.get(which);
// Wait for it to finish initialisation.
// Put me in its queue of waiters.
it.waiters.add(Thread.currentThread());
log(which, "Parking");
while (!it.ready.get()) {
// Park me.
LockSupport.park();
}
// I'm not waiting any more.
it.waiters.remove(Thread.currentThread());
log(which, "Unparked");
}
}
return it;
}
// Some simple logging.
static void log(int which, String s) {
log(new Date(), "Thread " + Thread.currentThread().getId() + " for Multiton " + which + " " + s);
}
static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
// synchronized so I don't need to make the DateFormat ThreadLocal.
static synchronized void log(Date d, String s) {
System.out.println(dateFormat.format(d) + " " + s);
}
// The tester class.
static class MultitonTester implements Runnable {
int which;
private MultitonTester(int which) {
this.which = which;
}
#Override
public void run() {
try {
Multiton.log(which, "Waiting");
Multiton m = Multiton.getInstance(which);
Multiton.log(which, "Got");
} catch (InterruptedException ex) {
Multiton.log(which, "Interrupted");
}
}
}
public static void main(String[] args) throws InterruptedException {
int testers = 50;
int multitons = 50;
// Do a number of them. Makes n testers for each Multiton.
for (int i = 1; i < testers * multitons; i++) {
// Which one to create.
int which = i / testers;
//System.out.println("Requesting Multiton " + i);
new Thread(new MultitonTester(which+1)).start();
}
}
}
I'm not a Java programmer, but: HashMap is not safe for concurrent access. Might I recommend ConcurrentHashMap.
private static final ConcurrentHashMap<Object, Multiton> instances = new ConcurrentHashMap<Object, Multiton>();
public static <TYPE extends Object, KEY extends Enum<Keys> & MultitionKey<TYPE>> Multiton getInstance(KEY id)
{
Multiton result;
synchronized (id)
{
result = instances.get(id);
if(result == null)
{
result = new Multiton();
instances.put(id, result);
}
}
System.out.println("Retrieved instance.");
return result;
}

Categories

Resources