ScoopsaHaagenDazs
ScoopsaHaagenDazs

Reputation: 39

Passing object by reference to a thread

Let's say I have a class called Object and a thread called ObjectCreator that manages the creation of an Object. For the sake of simplicity, Object has attributes: objectNumber and objectName.

If I were to create an instance of Object called instance, it would be held by ObjectCreator. Now let's say I needed another thread (let's call it ObjectChanger) to be able to see and manipulate instance; does it make sense to turn instance into a static Object?

I've managed to see results by making instance static so now I can do something like:

ObjectCreator.instance.getName();

Where getName() is a method of Object. From what I've read from answers to similar questions, static things are evil and there's always workarounds. One suggestion I've read is to pass instance to ObjectChanger as an argument for its constructor but what if instance wasn't created yet at the time I need to create an ObjectChanger?

Perhaps this question is more about OOP concepts than multi-threading or it may be a duplicate so forgive me but I'm quite lost here.

EDIT: To address frankie's and Jim's suggestions, here are some code snippets:

Object:

class Object

{
 private String objectName = "Something";
 private int objectNumber = 1;

 public synchronized void changeNumber(int newNumber)
 {
  objectNumber = newNumber;
 }
}

ObjectCreator:

class ObjectCreator extends Thread
{
 static Object instance;

 public ObjectCreator (Object something)
 {
  instance = something;
 }

 static void createObject()
 {
  ...
 }

 static Object getObject()
 {
  return instance;
 }
}

ObjectChanger:

public class ObjectChanger extends Thread
{
 private Object currentInstance = null;
 private int instanceNumber = null;

 public void run()
 {
  currentInstance = ObjectCreator.getObject(); //If I were to make getObject() non-static, this line churns up an error

  instanceNumber = currentInstance.getObjectNumber();
  currentInstance.changeNumber(2); //valid?
 }
}

Upvotes: 1

Views: 799

Answers (5)

afsantos
afsantos

Reputation: 5208

If you want a thread to obtain access to an object not created within it, you must ensure that said thread has a path of references which it can follow, leading to the new object.

Consider the following code, with no threads involved.

class MyObject { /* ... */ }

interface MyObjectProvider {
    MyObject getMyObject();
}

class Creator implements MyObjectProvider {
    private MyObject obj;
        /* ... */
    @Override
    public MyObject getMyObject() {
        return obj;
    }

    /** Invoked at some point in time. */
    void createMyObject() {
        obj = new MyObject();
    }
}

class Consumer {
    private MyObjectProvider provider;

    Consumer(MyObjectProvider mop) {
        provider = mop;
    }

    void consume() {
        // At some point in time...
        MyObject o = provider.getMyObject();
    }
}

Example of a program:

public static void main(String[] args) {
    Creator creator = new Creator();
    Consumer consumer = new Consumer(creator);

    creator.createMyObject();
    consumer.consume();
}

When you add threads to the mix, some code has to change, but the struture is the same. The idea is to run the Creator in a thread, and the Consumer in another, as you've pointed out. So, in short, these are the things you should be looking into:

  • Concurrency control: look into data races, synchronized, mutual exclusion, and their friends. Start here.
  • wait and notify, if the Consumer should wait for MyObject to be created. Look here.

When you have a nice grasp on these concepts, you may look into the volatile keyword (watch out for its pitfalls), and the java.util.concurrent package which provides better concurrency primitives, concurrent collections, and atomic variables.

Upvotes: 1

frankie liuzzi
frankie liuzzi

Reputation: 1720

Why cant you just make an getter in the ObjectCreator class that retrieves said Object?

ex: ObjectCreater.getMyObject()

EDIT:

I think you're looking for something like this if Im not mistaken:

public class ObjectCreator{
    ArrayList<Object> children;

    public ObjectCreator(){ 
         children = new ArrayList<Object>();
    }

    //returns back index in children array (for accessing from other threads)
    public int createObject( whatever params here ){
       Object o = new Object( params );
       children.add(o);
       return children.size()-1;
    }

}

since I dont know much about the problem you're trying to solve, Im not sure if it has to be thread safe, if you want these objects mapped, or accessed differently, but Im confused where all the confusion about static is coming...

Upvotes: 0

Salandur
Salandur

Reputation: 6453

If you only want to change the values of the fields of your class, you should just pass the object into your newly created thread. Then there is really no need to keep a static reference around in a holder class.

But as commented already, we need a bit more information to get to what you want to do with your object and thread.

Upvotes: 0

Jim Garrison
Jim Garrison

Reputation: 86764

This is just a skeleton showing the basic structure. Error handling is left as an exercise :-)

public class MyObject { ... }
...
public class MyObjectCreator { 
    private Map<String,MyObject> createdObjects = new HashMap<>();
    public MyObject makeNewObject(int objNum, String objName)
    {
        MyObject o = new MyObject(objNum, objName);
        this.createdObjects.put(objName,o);
    }
    public MyObject getObject(String objName)
    {
        return this.createdObjects.get(objName);
    }
}
...
public class MyProgram {
    public static void main(String[] args)
    {
        MyObjectCreator oc = new MyObjectCreator();
        MyObject        mo = oc.makeNewObject(10,"aNewObject");
    ...

    MyObject o = oc.get("aNewObject");
    ...

Upvotes: 0

An SO User
An SO User

Reputation: 24998

You can put your objects in a list structure like Vector and store them in the ObjectCreator. Add a getter method to ObjectCreator which will accept an index of the object to be received.

Upvotes: 0

Related Questions