0

I have a class(MapLoader) which loads a map.

public class MapLoader{
statci Map aMap;
static{
 //does some processing to load this map
}

This map is being used by two different jobs which runs parallely. These jobs are unix batch jobs which calls two different jar files.

Jar 1:
public class ABC{
public static void main(String args[]){
//uses MapLoader.aMap

}

Jar 2:
public class XYZ{
public static void main(String args[]){
//uses MapLoader.aMap

}

These jar files uses that map of class MapLoader.

Is there any way only one instance of MapLoader is created by both processes. Kindly suggest.

**Kindly ignore java syntax if any, I just wrote the code for explaining my issue.

King
  • 37
  • 5
  • We did something "kind of" similar by using a local RMI server which provided a centralised instance of a commonly used cache. You could do something similar with plain old `Socket`s, but you'd have to write a protocol to interact with the `MapLoader` rather than trying to serialize it across the wire, because then you end up with a separate instance... – MadProgrammer Jun 06 '14 at 04:55
  • How big of a requirement is running these mains in separate processes? – David Ehrmann Jun 06 '14 at 06:47
  • if you mean a single instance from a memory standpoint its not possible, but for the contents of the class, you could use Redis to share the content between VM's, this is a in-memory solution which is super fast – Anantha Sharma Jun 06 '14 at 06:51

5 Answers5

0

makeyour MapLoader as singleton class :

    private static MapLoader ml;
    public static MapLoader create ()

       {
           if (ml==null)
           {
              ml=new MapLoader ();
           }
           return (ml);
       }

create one new class where you create one instance of MapLoader :

    class OneInstance
       {
         public static returnOneInstance()
           {
               MapLoader mapLoader = MapLoader.create();
           };

Now, extend OneInstance class in your ABC and XYZ class, then it should solve your purpose..

Archana
  • 405
  • 4
  • 16
0

This is going to be way harder than you'd like!

If you're wanting to share objects in this manner then the best approach is to use threads rather than processes. Getting a Java based scheduler such as Quartz to do the scheduling amongst threads will be easier than getting IPC working between two Java processes.

If you must use two different processes then you are going to have to do IPC. Two Java processes can not share memory (excluding some JNI corner cases). That leaves you with approaches such as RMI, named pipes, shared files, sockets...

Kong
  • 8,792
  • 15
  • 68
  • 98
0

This map is being used by two different jobs which runs parallely

...by both processes...

You're using "process" in the OS sense, right? No, you can't share objects between JVM instances like that.

This sounds like a shared cache, so you might be better off using Memcached and having the first process to load "lock," then initialize it.

Community
  • 1
  • 1
David Ehrmann
  • 7,366
  • 2
  • 31
  • 40
  • Memcached! Now that's nuking OP's mosquito! – Kong Jun 06 '14 at 06:43
  • It's a relatively thin "DB, and it feels like it fits the use case. If Map is actually 1M key-value pairs memoized from a DB, Memcached is actually a really sensible choice. If we're sharing two values, it's a bit silly. – David Ehrmann Jun 06 '14 at 06:46
  • Agreed; but what's the chance user3671193 with 1 rep, who doesn't know two Java processes can't share memory has 1M+ key value pairs? – Kong Jun 06 '14 at 06:50
  • @Kong: I know two java processes cant share memory. But I thought of giving a try. May be intelligent people like you have found a way. :-D – King Jun 06 '14 at 07:02
  • @King: You could use JNI to do it if the library is available on the system; ```sys/shm.h``` calls, basically. – David Ehrmann Jun 06 '14 at 16:04
0

One pattern for concurrent initialisation is the enum. The other is an inner class (as that is guaranteed to load the inner class on first usage).

The usage will have to be adapted, as no longer a static field can be used.

public enum MapLoader {

     INSTANCE;

     public Map aMap;
     {
         //does some processing to load this map
         aMap = new ConcurrentHashMap();
     }
}

volatile aMap = MapLoader.INSTANCE.aMap;

This creates a singleton. I personally generally pass the shared instance to every thread in their constructor, or rely on some container (as in a web application) to provide a singleton.

Having the field volatile in the thread ensures that it is not only copied into the thread but on every access updated.

A ConcurrentHashMap ensures thread-safe modification.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • Again; OP's after a solution for doing this between two processes. – Kong Jun 06 '14 at 06:53
  • I didnt understood your solution. I dont need a static field. I just want both processes(each have 8 threads) to use only one single instance. Kindly elaborate your solution. – King Jun 06 '14 at 06:59
  • @user3671193 did that, but I am afraid a good tutorial is more enlightening (than any answer here). Unfortunately I would need to search for a link too. – Joop Eggen Jun 06 '14 at 07:09
0

You can do this by doing your MapLoader as singleton class

public class MapLoader {

    private static MapLoader map;



    public static MapLoader getInstance(){
        if(map== null){
            map= new MapLoader ();
        }
        return map;
    }
}

also visit this link

Community
  • 1
  • 1
Engineer
  • 1,436
  • 3
  • 18
  • 33