java中父进程与子进程

转自:https://my.oschina.net/hosee/blog/509557

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

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

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

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

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

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

首先我们来看一个网上很多人的例子:

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也会结束该程序)。

那么又有个思考,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

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java中,进程和线程是两种处理任务的抽象概念,它们的主要区别在于资源的占用和管理方式。 **进程(Process)** 进程是操作系统进行资源分配和任务调度的基本单位。一个进程可以有它自己的内存空间,包括代码、数据和系统资源(如文件描述符、端口等)。一个Java程序由一个主进程(主线程)和一些用户启动的子进程组成。进程是相对独立的,有自己的地址空间,除非终止,否则会一直存在。 **线程(Thread)** 线程是操作系统能够进行运算调度的最小单位。线程共享进程的部分资源,如内存空间和系统资源(如文件描述符、端口等)。Java中的线程由主线程和用户启动的子线程组成。一个Java应用程序由一个主线程和一些用户启动的子线程组成。主线程的创建和执行由JVM完成,而用户线程的创建和执行由用户代码完成。 主要区别如下: 1. **资源占用**:进程需要分配系统分配给该进程的所有资源,包括内存、CPU、文件描述符等。而线程只需要分配给当前线程的部分资源,如CPU时间片和内存栈。 2. **独立性**:进程是相对独立的单位,拥有自己的内存空间和系统资源。而线程是进程的一部分,它不能脱离主进程(父进程)而存在。 3. **调度方式**:进程是由操作系统负责调度的,系统调度进程使用它的资源。而线程则是操作系统调度同一进程中的多个线程,每个线程有自己的执行顺序,但共享进程的资源。 4. **并发性**:由于线程的并发性,多个线程可以同时执行,从而实现并发程序。而进程的并发性相对较低,因为操作系统通常按照一定的时间顺序切换到不同的进程执行。 5. **创建和销毁成本**:由于进程的管理和维护开销相对较大,因此在小型或特定情况下通常使用线程,而不在小型系统中使用进程。相反,大型系统或需要更高级别的隔离和控制的应用程序可能会使用进程来隔离资源和减少相互影响。 在实际使用中,开发者应根据实际情况选择合适的模型(单线程或多线程),以及如何管理和优化这些模型以提高程序的性能和效率。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值