假设我有一个名为Object的类和一个名为ObjectCreator的线程来管理Object的创建。为简单起见,Object具有属性:objectNumber和objectName。
如果我要创建一个名为Object的Object实例,它将由ObjectCreator保存。现在让我们说我需要另一个线程(让它称之为ObjectChanger)以便能够查看和操作实例;将实例转换为静态对象是否有意义?
我设法通过将实例设为静态来查看结果,所以现在我可以执行以下操作:
ObjectCreator.instance.getName();
其中getName()是Object的方法。从我从类似问题的答案中读到的东西,静态的东西是邪恶的,并且总是有变通方法。我读过的一个建议是将实例传递给ObjectChanger作为其构造函数的参数,但是如果在我需要创建ObjectChanger时还没有创建实例呢?
也许这个问题更多是关于OOP概念而不是多线程,或者它可能是重复的,所以原谅我,但我在这里很丢失。
编辑:为了解决frankie和Jim的建议,以下是一些代码段:
对象
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?
}
}
答案 0 :(得分:1)
如果您希望线程获得对其中未创建的对象的访问权限,则必须确保所述线程具有可以跟随的引用的路径,从而生成新对象。
考虑以下代码,不涉及任何线程。
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();
}
}
程序示例:
public static void main(String[] args) {
Creator creator = new Creator();
Consumer consumer = new Consumer(creator);
creator.createMyObject();
consumer.consume();
}
当您向混合添加线程时,某些代码必须更改,但结构是相同的。 正如你所指出的那样,我们的想法是在一个线程中运行Creator,在另一个线程中运行Consumer。 所以,简而言之,这些是你应该研究的事情:
synchronized
,互斥以及他们的朋友。 Start here。wait
和notify
,如果Consumer应该等待创建MyObject。 Look here。如果你对这些概念有了很好的把握,你可以查看volatile
关键字(注意其缺陷),以及提供更好的<{em}}的java.util.concurrent
包并发原语,并发集合和原子变量。
答案 1 :(得分:0)
为什么你不能在ObjectCreator类中创建一个获取所述对象的getter?
ex:ObjectCreater.getMyObject()
编辑:
如果我没记错的话,我认为你正在寻找类似的东西:
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;
}
}
因为我不太了解你要解决的问题,我不确定它是否必须是线程安全的,如果你想要映射这些对象,或者以不同的方式访问,但我很困惑,所有关于静态的混淆都在哪里来......
答案 2 :(得分:0)
您可以将对象放在Vector
等列表结构中,并将其存储在ObjectCreator
中。向ObjectCreator
添加一个getter方法,该方法将接受要接收的对象的索引。
答案 3 :(得分:0)
这只是一个显示基本结构的骨架。错误处理留作练习: - )
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");
...
答案 4 :(得分:0)
如果您只想更改类的字段值,则应该将对象传递给新创建的线程。然后,实际上没有必要在持有者类中保留静态引用。
但正如已经评论过的那样,我们需要更多的信息来了解你想要对你的对象和线程做些什么。