2013-11-14 142 views
1

比方说,我有一个名为Object的类和一个名为ObjectCreator的线程来管理对象的创建。为了简单起见,Object具有属性:objectNumber和objectName。通过引用线程传递对象

如果我要创建Object实例,它将由ObjectCreator保存。现在让我们说我需要另一个线程(让我们称之为ObjectChanger)来查看和操纵实例;将实例变成静态对象是否有意义?

我已经设法通过使例如静态的,所以现在我可以这样做,看看结果:

ObjectCreator.instance.getName(); 

其中的getName()为对象的一个​​方法。从我从类似问题的答案中读到的东西,静态的东西是邪恶的,总是有解决方法。我读过的一个建议是将实例作为其构造函数的参数传递给ObjectChanger,但是如果实例在创建ObjectChanger时尚未创建,该怎么办?

也许这个问题更多的是关于面向对象的概念,而不是多线程,或者它可能是重复的,所以原谅我,但我很迷茫。

编辑:为了解决弗兰基和吉姆的建议,这里有一些代码段:

对象:

类对象

{ 
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? 
} 
} 
+1

为什么要创建一个名为'Object'的类? Object类已经在Java中定义,并且是所有其他类的超类。 –

+0

对不起,我完全忘了这一点。我没有真正创建一个名为Object的类。我只在这个问题中将它命名为Object,认为它会更容易遵循。 – ScoopsaHaagenDazs

+2

你似乎对'static'的含义感到困惑。您需要以现有代码的形式提供更多的上下文,并解释您的最终目标。很难弄清楚你想在这里做什么。 –

回答

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(); 
} 

当您添加线程进来,一些代码有可能改变,但struture是一样的。 正如你指出的那样,这个想法是在一个线程中运行Creator,在另一个线程中运行Consumer。 因此,简而言之,这些都是你应该寻找到的东西:

  • 并发控制:考虑数据竞争,​​,相互排斥,和他们的朋友。 Start here
  • waitnotify,如果消费者应该等待MyObject创建。 Look here

当你对这些概念的一个很好的把握,你可以看到volatile关键字(注意它的缺陷),以及java.util.concurrent包,它提供更好并发原语,并发集合,和原子变量。

+0

有趣的答案,虽然我的接口知识是非常有限的。我想我遵循你的逻辑,我会尽力实现它。现在,我已经更新了我的代码片断,以表明我确实有意让多个线程通过同步方法来操作Object的实例。如果我要将我的过程转换为编码方式,那么是否还需要将changeNumber()方法放入接口中?或者我可以做一些像o.changeNumber(2);来自消费者类? – ScoopsaHaagenDazs

+1

你有在C编码的经验吗?如果是这样,请将接口视为'.h'文件。一个接口定义一个类型,与类相同,以及该类型的预期方法。一个接口承诺其实现者将定义已声明的方法,所以无论你在哪里获得对接口类型的引用,都不需要知道具体哪个类实现它。这是一种避免两个类彼此依赖的类的方法(在我的示例中,消费者<-> Creator)。消费者依赖于MyObjectProvider,因为它只是希望有人给它一个对象,它并不需要专门创建一个Creator。 – afsantos

+1

@ScoopsaHaagenDazs我不认为你需要MyObject中的方法的任何接口,让它保持原样。在创建它们之后,MyObject的实例是否将被两个线程使用?如果不是,则MyObject的方法不需要是“同步”的。但是,从另一个线程检索MyObject实例的方法可能需要同步。 – afsantos

0

为什么不能请你们在ObjectCreator类检索上述目标的消气?

例如: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; 
    } 

} 

,因为我不知道很多有关你试图解决的问题,我不知道它是否必须是线程安全的,如果你想这些对象映射,或访问不同,但我很困惑,所有关于静态的困惑来临...

+0

我也试过这个,但我似乎被迫使这个方法是静态的。调用ObjectCreator.getMyObject()在ObjectChanger中产生错误 – ScoopsaHaagenDazs

+0

这不是一个答案;它应该是一个评论。 –

+0

是的,如果你正在解决你构造的类限制,那么发布代码总是一个好主意。它可能迫使你使该方法成为静态的,因为ObjectCreator所制作的Object也是静态的。 ObjectCreator - 如果它拥有一个成员对象 - 不能是一个静态类。它也需要实例化,以便让getter可以访问成员变量。这有帮助吗? –

0

您可以将对象放在列表结构中,如Vector,并将它们存储在ObjectCreator中。将一个获取方法添加到ObjectCreator,该方法将接受要接收的对象的索引。

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"); 
    ... 
0

如果你只是想改变你的类的字段的值,你应该只传递对象插入到新创建的线程。那么真的不需要在持有者类中保留静态引用。

但是正如已经评论的那样,我们需要更多的信息来获得你想要的对象和线程。