How to share a singleton between threads (controller)

1,046 views
Skip to first unread message

kheraud

unread,
Aug 4, 2011, 12:24:54 PM8/4/11
to play-framework
Hello,

I have to launch computation tasks which last long (in fact to dialog
with Apple Push Notification service for many smartphones). To do so I
plan to set up a Play! server and use Jobs launched by user
(authenticated) requests.
I need a way to trace jobs launched / finished / to be replayed... in
order not to have the same user launching two parallel jobs. To do so
I am trying to build a thread-safe singleton shared by controllers.

As in Play! all is based on static methods, am I doomed to have a
"singleton" with only static methods / fields. Is there a way to have
a singleton object instanciated and shared by controllers ?

Thanks for your help !

kheraud

Adam Jorgensen

unread,
Aug 4, 2011, 3:29:26 PM8/4/11
to play-fr...@googlegroups.com
Like a database?


--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To post to this group, send email to play-fr...@googlegroups.com.
To unsubscribe from this group, send email to play-framewor...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/play-framework?hl=en.


Karim Heraud

unread,
Aug 4, 2011, 6:07:25 PM8/4/11
to play-fr...@googlegroups.com
Yes like a database. But I want to avoid using a database. I am already linked to an old one which I can't change the schema.
As I am trying to avoid dealing with 2 databases, I chose to go for a kind of singleton. Persistence of data isn't required for this service.
Karim Heraud
Mob: 06.31.21.24.27

Adam Jorgensen

unread,
Aug 5, 2011, 12:01:50 AM8/5/11
to play-fr...@googlegroups.com
It sounds like you really should use a database because trying to hack in state sharing between threads is going directly against the
shared-nothing philosophy of Play...

green

unread,
Aug 5, 2011, 1:45:30 AM8/5/11
to play-fr...@googlegroups.com
How about using Cache ?

Karim Heraud

unread,
Aug 5, 2011, 4:36:37 AM8/5/11
to play-fr...@googlegroups.com
@Adam Jorgensen : You are very right. But I have already tried some weeks ago to make Play! work with 2 db. It lead to a very strong lose of performance (probably caused by how i implemented it). I plan to retry playing with that with Play! 1.3 (http://play.lighthouseapp.com/projects/57987/tickets/706-multiple-databasejpa-support)
@Green : Could be great even if cache is not guarantee. I will give a try to memcahcheq (http://memcachedb.org/memcacheq/)

Thanks for your help !

Adam Jorgensen

unread,
Aug 5, 2011, 5:45:55 AM8/5/11
to play-fr...@googlegroups.com
Memcachedb looks like the way go.

martin

unread,
Aug 5, 2011, 7:38:18 AM8/5/11
to play-framework
Hi,
if you have only one instance you can easily use singletons. Just
don't use Controller's static fields:

From Play's samples:

public class ChatRoom {
...
static ChatRoom instance = null;
public static ChatRoom get() {
if(instance == null) {
instance = new ChatRoom();
}
return instance;
}

}

If you are going to distribute your app to more instances, you can
simply extend your singleton to use an external storage later on.

Karim Heraud

unread,
Aug 5, 2011, 8:03:49 AM8/5/11
to play-fr...@googlegroups.com
Thanks for the example, it is exactly what I am trying to do

Thanks a lot

green

unread,
Aug 5, 2011, 8:35:19 AM8/5/11
to play-fr...@googlegroups.com
This approach is okay if one JVM is enough for your service. Suppose you need multiple play instances deployed on multiple boxes Singleton approach fails immediately while database and memcache approachese are still effective.

Yann Simon

unread,
Aug 5, 2011, 8:40:57 AM8/5/11
to play-fr...@googlegroups.com
Be aware that the example if not thread-safe.
If 2 threads try to access the get() at the same time, you can have 2
instances at the end.
You need to synchronize the method, and use synchronisation inside the
method, with all the dangers it represent
(see 'The "Double-Checked Locking is Broken" Declaration':
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html)

If you do not need lazy loading of the singleton, use directly:
public class ChatRoom {
private static final ChatRoom instance = new ChatRoom();
public static ChatRoom get() { return instance; }
}

If you need lazy loading, you can use an enum for this
public enum ChatRoom {
INSTANCE;
public static ChatRoom get() { return INSTANCE; }

// you can use the constructor for lazy loading
}

Do not forget that you have one singleton pro JVM.
To be more precise, you have one singleton pro classloader.
If 2 classloaders load the singleton, you will have 2 instances.

For more information, read:
http://java.sun.com/developer/technicalArticles/Programming/singletons/
Citation:
" Multiple Singletons Simultaneously Loaded by Different Class Loaders

When two class loaders load a class, you actually have two copies
of the class, and each one can have its own Singleton instance. That
is particularly relevant in servlets running in certain servlet
engines (iPlanet for example), where each servlet by default uses its
own class loader. Two different servlets accessing a joint Singleton
will, in fact, get two different objects.

Multiple class loaders occur more commonly than you might think.
When browsers load classes from the network for use by applets, they
use a separate class loader for each server address. Similarly, Jini
and RMI systems may use a separate class loader for the different code
bases from which they download class files. If your own system uses
custom class loaders, all the same issues may arise.

If loaded by different class loaders, two classes with the same
name, even the same package name, are treated as distinct -- even if,
in fact, they are byte-for-byte the same class. The different class
loaders represent different namespaces that distinguish classes (even
though the classes' names are the same), so that the two MySingleton
classes are in fact distinct. (See "Class Loaders as a Namespace
Mechanism" in Resources.) Since two Singleton objects belong to two
classes of the same name, it will appear at first glance that there
are two Singleton objects of the same class."

Yann

2011/8/5 Karim Heraud <khe...@gmail.com>:

martin

unread,
Aug 8, 2011, 4:04:17 PM8/8/11
to play-framework
@ Yann
You are absolutely right

@ green
I still think starting with this kind of approach is a good idea. As I
said you can easily re factor this singleton later on to connect to an
external service, rather than using the local jvm to store your state.
Just use a well designed interface and you only have to change code in
the singleton class and nothing else.
> 2011/8/5 Karim Heraud <kher...@gmail.com>:
> > kher...@gmail.com
Reply all
Reply to author
Forward
0 new messages