Java 在自定义线程中创建的对象在主线程上运行

Java 在自定义线程中创建的对象在主线程上运行,java,android,multithreading,Java,Android,Multithreading,在Android上,我有一个MyThread类,它扩展了线程。在MyThread中,我声明了一些对象,并在run()方法中初始化它们。这些对象是具有自己构造函数的自定义类的实例。其中一些会触发另一个后台线程并接受侦听器对象,这些对象也在MyThread的run()方法中初始化。我的问题是,这些侦听器是在主线程上执行的,而不是在MyThread上执行的 因此,我的问题是:在自定义线程上实例化的自定义对象的方法是在哪个线程上执行的?在哪个线程上创建对象并不重要,重要的是从哪个线程调用对象上的方法 例

在Android上,我有一个MyThread类,它扩展了线程。在MyThread中,我声明了一些对象,并在run()方法中初始化它们。这些对象是具有自己构造函数的自定义类的实例。其中一些会触发另一个后台线程并接受侦听器对象,这些对象也在MyThread的run()方法中初始化。我的问题是,这些侦听器是在主线程上执行的,而不是在MyThread上执行的


因此,我的问题是:在自定义线程上实例化的自定义对象的方法是在哪个线程上执行的?

在哪个线程上创建对象并不重要,重要的是从哪个线程调用对象上的方法

例如:

class MyThread extends Thread {

    public MyObject myObject;

    @Override
    public void run() {
        myObject = new MyObject();

        /* Do stuff */
    }

}
使用此类:

MyThread myThread = new MyThread();
myThread.start();
myThread.myObject.someMethod();

在这里,
someMethod
调用是在主线程上完成的。

在哪个线程上创建对象并不重要,重要的是从哪个线程调用对象上的方法

例如:

class MyThread extends Thread {

    public MyObject myObject;

    @Override
    public void run() {
        myObject = new MyObject();

        /* Do stuff */
    }

}
使用此类:

MyThread myThread = new MyThread();
myThread.start();
myThread.myObject.someMethod();

在这里,
someMethod
调用是在主线程上完成的。

不管它们在哪个线程上实例化,对象(以及您的侦听器)都可以从引用它们的任何线程访问(这样做是否安全是另一个问题)


对象不存在于任何线程上-当您从线程a调用对象上的方法时,该方法中的代码将在线程a上运行,而不管对象是在哪个线程上创建的。

在哪个线程上实例化对象(以及您的侦听器)并不重要可以从引用它们的任何线程访问(这样做是否安全是另一个问题)


对象在任何线程上都不存在-当您从线程a调用对象上的方法时,该方法中的代码将在线程a上运行,而不管对象是在哪个线程中创建的。

当程序启动时,聚会前是一个空房间。然后爱丽丝拿着她的手提包进来,开始清理东西。过了一会儿,爱丽丝给鲍勃打电话,后来鲍勃来厨房帮爱丽丝。爱丽丝和鲍勃准备了一些糖果,过了一会儿,史蒂夫和莎拉拿着啤酒和薯条敲门

爱丽丝、鲍勃、史蒂夫和莎拉是线程。爱丽丝是主要人物,因为她组织了这次聚会。糖果、啤酒和薯条是目标。注意史蒂夫带来了薯条,但是爱丽丝也可以吃!莎拉负责啤酒,但其他人当然可以喝。谁(哪个线程)把什么(创建的对象)带到聚会上并不重要:记忆是在红人之间共享的

现在,让我们看看你的Alice是如何工作的。Android应用程序的主线程是一个事件循环,可以看作:

while (running) {
  if (input != null) dispatch(input);
  sleepForSomeTime();
}
dispatch()
的调用最终将到达侦听器代码,以便在处理触摸事件的同一线程上执行。谁创建了对象、谁注册了侦听器等等都无关紧要

我认为您的应用程序并非如此,但实际上可能需要在后台线程池中处理事件。这是通过给线程一个要完成的任务队列,并让事件驱动的代码更新该队列(或者您可以使用
java.util.concurrent
中的executors框架)来实现的

请注意,您不应该在构造函数内启动线程,因为

  • 某些对象在完全构造之前可能会被看到(如果使用内部类或匿名类)
  • 构造函数的目的是初始化字段。背景线程的创建应由新构造对象的用户处理

  • 当一个程序启动时,在聚会之前它是一个空房间。然后爱丽丝拿着她的手提包进来,开始清理东西。过了一会儿,爱丽丝给鲍勃打电话,后来鲍勃来厨房帮爱丽丝。爱丽丝和鲍勃准备了一些糖果,过了一会儿,史蒂夫和莎拉拿着啤酒和薯条敲门

    爱丽丝、鲍勃、史蒂夫和莎拉是线程。爱丽丝是主要人物,因为她组织了这次聚会。糖果、啤酒和薯条是目标。注意史蒂夫带来了薯条,但是爱丽丝也可以吃!莎拉负责啤酒,但其他人当然可以喝。谁(哪个线程)把什么(创建的对象)带到聚会上并不重要:记忆是在红人之间共享的

    现在,让我们看看你的Alice是如何工作的。Android应用程序的主线程是一个事件循环,可以看作:

    while (running) {
      if (input != null) dispatch(input);
      sleepForSomeTime();
    }
    
    dispatch()
    的调用最终将到达侦听器代码,以便在处理触摸事件的同一线程上执行。谁创建了对象、谁注册了侦听器等等都无关紧要

    我认为您的应用程序并非如此,但实际上可能需要在后台线程池中处理事件。这是通过给线程一个要完成的任务队列,并让事件驱动的代码更新该队列(或者您可以使用
    java.util.concurrent
    中的executors框架)来实现的

    请注意,您不应该在构造函数内启动线程,因为

  • 某些对象在完全构造之前可能会被看到(如果使用内部类或匿名类)
  • 构造函数的目的是初始化字段。背景线程的创建应由新构造对象的用户处理

  • 可能在你问的问题的结尾没有找到你想要的答案。可能在你问的问题的结尾没有找到你想要的答案。我将重新表述“使用此线程”-你的意思是否是三行代码在所述线程上执行是不明确的,或者您是否正在描述所述线程的用法。-+1对于edit,我不明白的是为什么Android ist autom的util.Log.d()是