如果线程只能访问具有自己的实例的类的静态方法,由不同的线程创建,那么它将执行什么线程?

时间:2014-06-29 01:22:17

标签: java android multithreading runnable ui-thread

假设我有一个带有2个公共静态方法的类,它控制着它自己的单个私有实例。该课程的基本结构如下:

public class MyClass {
    private static MyClass myclass = null;
    private final Process, OutputStreamWriter, Strings, ints, etc....
    private class constructor....    
    private class methods....  

    public static void command(String cmd) {
        if(myclass == null) {
            myclass = new MyClass();
        }
        myclass.setCmd(cmd);
    }

    public static void execute() {
        myclass.run();
        myclass.close();
    }
}

我在Android应用程序中使用它,我只是想在我进行远程设计之前验证它是如何工作的。假设该类的命令来自UI线程。 UI线程调用第一个静态方法

MyClass.command("parse and do what's in this string");

现在我希望MyClass.execute()调用在某些情况下可能需要几乎一秒才能完成。我基本上只想验证如果我从Service或Runnable调用MyClass.execute()方法,那么执行将在该线程上发生。

在帖子static-method-behavior-in-multi-threaded-environment-in-java selig中声明:

  

java中的内存分为两类 - 堆和堆栈。堆是所有对象都存在的地方,堆栈是线程工作的地方。每个线程都有自己的堆栈,无法访问其他堆栈。每个线程还有一个指向代码的指针,指向它们当前正在运行的代码位。

     

当一个线程开始运行一个新方法时,它将该方法中的参数和局部变量保存在它自己的堆栈上。这些值中的一些可能是指向堆上对象的指针。如果两个线程同时运行相同的方法,它们的代码指针都会指向该方法,并且在它们的堆栈上有自己的参数和局部变量副本....

现在,由于UI线程调用了静态方法MyClass.command(“Do this”),它在技术上实例化了该类的私有本地参数和变量,这意味着该类位于UI线程的堆???这意味着如果我从服务线程或可运行线程调用MyClass.execute(),实际执行将在UI线程上发生,而服务或runnable等待它?我对此的理解是否正确?

谢谢!

3 个答案:

答案 0 :(得分:4)

好的,你的帖子中有很多错误信息。

1)默认情况下,服务和Runnables没有自己的线程。服务在UI线程上运行,尽管它们可以创建一个线程(默认情况下IntentService会这样做)。 Runnables在运行它们的任何线程调用上运行。但除非你将它们发布到附加到另一个线程或Thread对象的Handler,否则他们不会开始一个新的。

2)所有Java对象都在堆上,而不是堆栈。堆栈只保存基本类型和对象的引用(但对象本身在堆上)。

3)是的,每个Thread都有自己的堆栈,因此它可以拥有自己的一组局部变量。但这并不能阻止它接触堆上的任何东西。这包括程序中的任何对象

4)Thread中唯一私有的东西是函数中的局部变量。并注意到任何本地对象仍然在堆上,并且可以保存对它的引用并将其传递给另一个线程。

5)绝对没有什么限制线程只调用静态方法。您可以调用任何类型的方法。

答案 1 :(得分:1)

类不在堆栈上。线程和类之间没有交互。

如果调用方法(包括MyClass.execute()),该方法将在与调用者相同的线程上运行。因此,如果您从服务中调用它,它将在服务的线程中运行(但请注意,这也可能是UI线程,除非您使服务在单独的线程中运行!)。如果你从一个随机线程调用它,它将在该线程上运行。

堆栈对于理解Java代码的作用并不重要。

答案 2 :(得分:1)

  

这是否意味着该类位于UI线程的堆栈中?

您正在混淆引用对象

Java中的对象总是。每个线程都有自己的引用副本到自己堆栈中的对象。因此,command()所做的任何更改都会影响其引用位于堆栈上的对象 - 引用本身以及堆栈上的所有其他值都将保持不变,因为实体正在被更改在堆上。

  

这意味着如果我从服务线程或可运行线程调用MyClass.execute(),那么当服务或runnable等待它时,UI线程上是否会发生实际的执行?

如果从另一个线程调用MyClass.execute(),则execute()的代码将在该不同的线程上执行。每个线程都会跟踪其他线程正在执行独立的代码。因此,如果您从另一个线程调用MyClass.execute(),执行将神奇地传输到UI线程,并且将独立于其他线程发生,但任何共享对象除外。