我正在制作一些用java编写的软件,它涉及一个单一的父母'调用在自己的线程中运行的许多类(节点)的类(扩展Thread)。
类将父类存储为变量。如果节点类从父类调用方法,每个节点是否存储父对象的副本,或者所有节点是否对同一对象起作用?如果所有节点都作用于同一个对象,那么被调用函数中的do语句是在节点的线程中运行还是在父类的线程中运行?
EX代码:
class parent
{
ArrayList<node> nodes = new ArrayList<node>();
void createStartNodes()
{
for(int i =0; i < 36;++i)
{
nodes.put(i,new node(this));
nodes.get(i).start();
}
}
void callSomeFunc()
{
/* things */
}
}
class node extends Thread
{
parent par;
public node(parent p)
{
par=p;
}
@Override
public void run()
{
par.callSomeFunc();
}
}
答案 0 :(得分:5)
我觉得你很困惑。我只想在回答你的问题之前澄清这些问题:
类不会“在线程中运行”,因为它不会“运行”。您可以运行方法,而不是类。 根据您调用它的位置,可以在不同的线程中执行类的方法。
在扩展Thread
课程时(请注意大写字母T),您应覆盖run()
方法,而不是start()
方法,否则多线程的东西不会发生。但是,您确实必须调用 start()
,在Thread类中定义,而后者将在创建的线程中调用您的run()
方法,正如你所料。
[编辑:这一点在OP的编辑中显然得到了解决]
话虽如此,回到你的实际问题:
每个节点都存储父对象的副本或执行所有节点 对同一个对象采取行动?
每个java对象(读取非基本类型)只是一个引用,您不传递对象值。因此,所有节点都存储对同一对象的引用,因为在调用构造函数时,它们向同一对象提供了引用(this
)。
调用函数中的do语句在节点的线程中运行 在父类的线程中?
在代码的当前状态中,您不会覆盖(由OP解决) run()
而是覆盖start()
,因此您无论如何都没有多个线程。
run()
方法中执行的代码将在节点的线程中执行,即使从run()
调用其他方法也是如此。
旁注:这是因为您正确调用了node.start()
。如果您直接调用node.run()
,则会在您调用run()
的帖子中执行。
答案 1 :(得分:1)
首先,你不应该覆盖Thread
类的start()方法,你应该调用它。并且类似地,你不应该调用Thread类的run()方法,你应该覆盖它。
所以当你打电话给你的父母&#34; run()方法中的类,它在新实例中起作用,而不是由您创建的所有其他线程共享。
编辑:你已经过去了#34;这个&#34;对于构造函数,它们将共享相同的对象。
答案 2 :(得分:1)
每个节点是存储父对象的副本还是所有节点都作用于同一对象?
它们每个都存储指向父对象的内存位置的指针。他们确实对同一个对象采取行动。
如果所有节点都作用于同一个对象,那么被调用函数中的do语句是在节点的线程中运行还是在父类的线程中运行?
它们在尝试修改父对象的节点的线程中运行。您可能希望确保在执行此操作时正确使用同步,例如使用synchronized
块。否则,当存在对父对象的并发访问时,可能会出现不正确/不一致的行为。例如:
class Node extends Thread
{
Parent par;
public Node(Parent p)
{
par=p;
}
@Override
public void run()
{
synchronized(par) {
par.callSomeFunc();
}
}
}
synchronized
块将为该线程提供对父对象的独占访问权。
此外,线程特定逻辑应该在run
方法中,而不在start
方法中。