Reputation: 39
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
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:
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
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
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
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
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