主线程 (Main) 与子线程的关系

最近在和同事讨论 java 主线程和子线程之间的关系,自己也到网上搜索了下,发现各种答案都有,有些还是互相矛盾的。经过测试自己得出以下几个结论,跟大家分享下,如果有错误,欢迎大牛指正,帮助我这只小菜鸟。废话不多说,直接上结论:

(一)Main 线程是个非守护线程,不能设置成守护线程。

          这是因为,main线程是由java虚拟机在启动的时候创建的。main方法开始执行的时候,主线程已经创建好并在运行了。对于运行中的线程,调用Thread.setDaemon()会抛出异常Exception in thread "main"     java.lang.IllegalThreadStateException。测试代码如下:

[java] view plain copy

  1. public class MainTest

  2. {

  3. public static void main(String[] args)

  4. {

  5. System.out.println(“ parent thread begin ”);

  6. Thread.currentThread().setDaemon(true);

  7. }

  8. }

**(二)Main 线程结束,其他线程一样可以正常运行。 **

       主线程,只是个普通的非守护线程,用来启动应用程序,不能设置成守护线程;除此之外,它跟其他非守护线程没有什么不同。主线程执行结束,其他线程一样可以正常执行。代码如下:

[java] view plain copy

  1. public class ParentTest

  2. {

  3. public static void main(String[] args)

  4. {

  5. System.out.println(“parent thread begin ”);

  6. ChildThread t1 = new ChildThread(“thread1”);

  7. ChildThread t2 = new ChildThread(“thread2”);

  8. t1.start();

  9. t2.start();

  10. System.out.println(“parent thread over ”);

  11. }

  12. }

  13. class ChildThread extends Thread

  14. {

  15. private String name = null;

  16. public ChildThread(String name)

  17. {

  18. this.name = name;

  19. }

  20. @Override

  21. public void run()

  22. {

  23. System.out.println(this.name + “–child thead begin”);

  24. try

  25. {

  26. Thread.sleep(500);

  27. }

  28. catch (InterruptedException e)

  29. {

  30. System.out.println(e);

  31. }

  32. System.out.println(this.name + “–child thead over”);

  33. }

  34. }

  35. –程序运行结果如下:

[java] view plain copy

  1. parent thread begin

  2. parent thread over

  3. thread2–child thead begin

  4. thread1–child thead begin

  5. thread2–child thead over

  6. thread1–child thead over

这样其实是很合理的,按照操作系统的理论,进程是资源分配的基本单位,线程是 CPU 调度的基本单位。对于 CPU 来说,其实并不存在 java 的主线程和子线程之分,都只是个普通的线程。进程的资源是线程共享的,只要进程还在,线程就可以正常执行,换句话说线程是强依赖于进程的。也就是说,线程其实并不存在互相依赖的关系,一个线程的死亡从理论上来说,不会对其他线程有什么影响。

(三)Main 线程结束,其他线程也可以立刻结束,当且仅当这些子线程都是守护线程。

   java虚拟机(相当于进程)退出的时机是:虚拟机中所有存活的线程都是守护线程。只要还有存活的非守护线程虚拟机就不会退出,而是等待非守护线程执行完毕;反之,如果虚拟机中的线程都是守护线程,那么不管这些线程的死活java虚拟机都会退出。测试代码如下:

[java] view plain copy

  1. public class ParentTest

  2. {

  3. public static void main(String[] args)

  4. {

  5. System.out.println(“parent thread begin ”);

  6. ChildThread t1 = new ChildThread(“thread1”);

  7. ChildThread t2 = new ChildThread(“thread2”);

  8. t1.setDaemon(true);

  9. t2.setDaemon(true);

  10. t1.start();

  11. t2.start();

  12. System.out.println(“parent thread over ”);

  13. }

  14. }

  15. class ChildThread extends Thread

  16. {

  17. private String name = null;

  18. public ChildThread(String name)

  19. {

  20. this.name = name;

  21. }

  22. @Override

  23. public void run()

  24. {

  25. System.out.println(this.name + “–child thead begin”);

  26. try

  27. {

  28. Thread.sleep(500);

  29. }

  30. catch (InterruptedException e)

  31. {

  32. System.out.println(e);

  33. }

  34. System.out.println(this.name + “–child thead over”);

  35. }

  36. }

  37. 执行结果如下:

  38. parent thread begin

  39. parent thread over

  40. thread1–child thead begin

  41. thread2–child thead begin