使用Thread分配内存

pet*_*ter 3 java multithreading memory-management

我想知道如果在方法中声明一个本地线程会发生什么?通常,函数返回后,所有局部变量都将消失,因为它们都在Stack上分配.然而,似乎本地线程将是一个不同的故事.是对的吗?

public int A() {
    Thread t = new Thread() {
        doSomething();
    }
    t.start();
    return -1;
 }
Run Code Online (Sandbox Code Playgroud)

Joh*_*int 14

线程是它自己的GC根.因此,无论何时创建线程,无论其创建上下文如何,在其运行方法完成之前,它都不会准备好GC.即使本地方法完成且线程仍处于活动状态,也是如此.

例:

public void doSomeAsync(){
   Thread th = new Thread(new Runnable(){
      public void run(){
          Thread.sleep(500);
      }
   });
   th.start();
   //do something else quickly
}
Run Code Online (Sandbox Code Playgroud)

//do somethign else quickly没有转义的任何定义之后,该方法被标记为GC.线程th将不会被标记为GC并且正确地放置在具有自己的线程堆栈的堆上.


Gra*_*ray 7

约翰的答案很好,但我想我会补充一些细节.这是一个代码示例,我将用它来显示特定的变量用法.

 public void startThread() {
      long var1 = 10;
      byte[] var2 = new byte[1024];
      final byte[] var3 = new byte[1024];
      final byte[] var4 = new byte[1024];
      Thread thread = new Thread(new Runnable() {
          private long var5 = 10;
          private byte[] var6 = new byte[1024];
          public void run() {
              int var7 = 100;
              byte[] var8 = new byte[1024];
              System.out.println("Size of var4 is " + var4.length);
              baz();
              ...
          }
          private void baz() {
              long var9 = 2;
              byte[] var10 = new byte[1024];
              ...
          }
      });
      thread.start();
 }
Run Code Online (Sandbox Code Playgroud)

所以我们在线程周围分配了许多变量.我们还有Thread对象本身以及Runnable线程正在运行的目标.

  • thread - 虽然它看起来是本地的startThread(),但是关联Thread也是由JVM管理的.run()方法完成后只有GC'd,Thread并由JVM 收集.在ThreadGC'd之后,所有使用的字段Thread都可以进行GC.
  • Runnable - 这个匿名类是线程正在运行的.它可以在Thread完成后进行GC 并且是GC'd.
  • var1 - 这是startThread()堆栈的本地和分配.当startThread()方法完成并重复使用堆栈时,它将被覆盖.
  • var2 - 这是startThread()在堆上本地并分配的.它不能被线程使用,因为它不是final.startThread()完成后可以GC'd .
  • var3 - 这是startThread()在堆上本地并分配的.这是final因为它可以被线程使用,但事实并非如此.startThread()完成后可以GC'd .
  • var4 - 这是startThread()在堆上本地和分配的.这是final并且由线程使用.它只能在两个后GC'd startThread()方法完成,并RunnableThread被GC'd.
  • var5 - 这是一个局部字段Runnable,在堆上作为Runnable匿名类的一部分进行分配.它可以在Runnable完成之后进行GC Runnable并且Thread是GC'd.
  • var6 - 这是一个局部字段Runnable,在堆内分配.它可以在Runnable完成之后进行GC Runnable并且Thread是GC'd.
  • var7 - 这是run()方法内部的本地字段,并在新线程的堆栈上分配.当run()方法完成并重复使用堆栈时,它将被覆盖.
  • var8 - 这是run()方法内部的一个局部字段,并在堆上分配.run()方法完成后可以进行GC'd .
  • var9 - 这是baz()方法内部的本地字段,并在新线程的堆栈上分配.当baz()方法完成并重复使用堆栈时,它将被覆盖.
  • var10 - 这是baz()方法内部的局部字段,并在堆上分配.baz()方法完成后可以进行GC'd .

结合其他笔记:

  • 如果新线程从未启动过,那么一旦startThread()完成就可以进行GC .将Runnable和所有与它相关的变量,可以再GC'd为好.
  • 如果在线程中final long varX声明startThread()并使用了原语,那么它必须在堆而不是堆栈上分配.当startThread()完成它仍然在使用.