Java中的父线程与子线程

之前在学习操做系统的时候,一直记得的父线程死后,子线程也消失了。然而今天在查资料中,发现有点疑惑,在此记录一下。 java

Java编写的程序都运行在Java虚拟机(JVM)中,在JVM的内部,程序的多任务是经过线程来实现的。 安全

每用java命令启动一个java应用程序,就会启动一个JVM进程。在同一个JVM进程中,有且只有一个进程,就是它本身。在这个JVM环境中,全部程序代码的运行都是以线程来运行的。JVM找到程序的入口点main(),而后运行main()方法,这样就产生了一个线程,这个线程称之为主线程。当main方法结束后(没有其余线程时),主线程运行完成。JVM进程也随即退出。 服务器

操做系统将进程线程进行管理,轮流(没有固定的顺序)分配每一个进程很短的一段时间(不必定是均分),而后在每一个进程内部,程序代码本身处理该进程内部线程的时间分配,多个线程之间相互的切换去执行,这个切换时间也是很是短的。 jvm

对于程序来讲,若是主进程在子进程还未结束时就已经退出,那么Linux内核会将子进程的父进程ID改成1(也就是init进程),当子进程结束后会由init进程来回收该子进程。 ide

那若是是把进程换成线程的话,会怎么样呢?假设主线程在子线程结束前就已经退出,子线程会发生什么? 学习

首先咱们来看一个网上不少人的例子: spa

package test;

public class Test1 extends Thread
{
	@Override
	public void run()
	{
		while (true)
		{
			try
			{
				Thread.sleep(2000);
			}
			catch (InterruptedException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("我还活着");
		}
	}

	public static void main(String[] args) throws InterruptedException
	{
		Thread t = new Test1();
		t.start();
		Thread.sleep(5000);
		System.out.println("Main End");
	}
}



输出:

我还活着
我还活着
Main End
我还活着
我还活着



上文说了 JVM找到程序的入口点main(),而后运行main()方法,这样就产生了一个线程,这个线程称之为主线程。当main方法结束后(没有其余线程时),主线程运行完成。JVM进程也随即退出。然而上述输出代表当main()运行到最后后,子线程依然在输出。因此你们就得出告终论,父线程要等待子线程完成后才会退出。然而咱们再看个例子:

package test;

public class Test extends Thread
{
	@Override
	public void run()
	{
		Thread sonthread = new a();
		sonthread.start();
	}

	public static void main(String[] args) throws InterruptedException
	{
		Thread fatherThread = new Test();
		fatherThread.start();
		Thread.sleep(5000);
		fatherThread.interrupt();
		Thread.sleep(2000);
		System.out.println("fatherThread.isAlive()?  "+fatherThread.isAlive());
	}
}

class a extends Thread
{
	@Override
	public void run()
	{
		while (true)
		{
			try
			{
				Thread.sleep(1000);
			}
			catch (InterruptedException e)
			{
				e.printStackTrace();
			}
			System.out.println("我还活着");
		}
	}
}



输出:

我还活着
我还活着
我还活着
我还活着
我还活着
我还活着
fatherThread.isAlive()?  false
我还活着
我还活着
我还活着



很明显,父线程死后子线程还在输出。两个例子到底哪一个是正确的呢?

查了不少资料获得了解答。 操作系统

若是main方法中没有建立其余线程,那么当main方法返回时JVM就会结束Java应用程序。但若是main方法中建立了其余线程,那么JVM就要在主线程和其余线程之间轮流切换,保证每一个线程都有机会使用CPU资源,main方法返回(主线程结束)JVM也不会结束要一直等到该程序全部线程所有结束才结束Java程序(另一种状况是:程序中调用了Runtime类的exit方法,而且安全管理器容许退出操做发生。这时JVM也会结束该程序)。 .net

那么又有个思考,JVM是怎么知道线程都结束的呢? 线程

JVM中有一个线程DestroyJavaVM,执行main()的线程在main执行完后调用JNI中的jni_DestroyJavaVM()方法唤起DestroyJavaVM线程。JVM在Jboss服务器启动以后,就会唤起DestroyJavaVM线程,处于等待状态,等待其它线程(java线程和native线程)退出时通知它卸载JVM。线程退出时,都会判断本身当前是不是整个JVM中最后一个非deamon线程,若是是,则通知DestroyJavaVM线程卸载JVM。ps:扩展一下:1.若是线程退出时判断本身不为最后一个非deamon线程,那么调用thread->exit(false),并在其中抛出thread_end事件,jvm不退出。2.若是线程退出时判断本身为最后一个非deamon线程,那么调用before_exit()方法,抛出两个事件: 事件1:thread_end线程结束事件、事件2:VM的death事件。而后调用thread->exit(true)方法,接下来把线程从active list卸下,删除线程等等一系列工做执行完成后,则通知正在等待的DestroyJavaVM线程执行卸载JVM操做。

因此第一个例子时,主线程运行完,可是它不是最后一个非守护线程,因此JVM并无退出,因此子线程还会继续运行。

第二个例子。主线程一直在,因此JVM不会退出。当父线程死去后,子线程还在运行。说明父线程的生命周期与子线程没有关系。

参考资料:

1. http://warnerhit.iteye.com/blog/1407484

2. http://liyuanlife.com/blog/2015/04/08/influence-of-main-threads-exiting-to-child-thread/

3. http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp47

4. http://jinguo.iteye.com/blog/747256

相关文章
相关标签/搜索