一、线程的生命周期
线程生命周期有新建状态、就绪状态、运行状态、阻塞状态和死亡状态五种基本状态。其中阻塞状态又可细分为等待阻塞、同步阻塞和其他阻塞。如下图所示:
- 新建状态(New)
创建一个新的线程,即新建状态。java中创建一个线程的四种方式:
(1)一种是继承Thread类,重写run()方法;
(2)第二种是实现Runnable接口,重写run()方法;
(3)使用Callable和Future创建线程;
(4)使用线程池例如用Executor框架。 - 就绪状态(Runnable)
当线程对象调用strat(),方法之后,线程就进入了就绪状态,等待CPU的调度执行,CPU调度线程是一个不确定的过程,当CPU没有调度线程的时候,线程是不执行的,当CPU调度的时候,线程才会执行。当运行状态的一个线程执行yield()函数或者时间片用完时,会进入到就绪状态。比如课堂老师随机点名的时候,在教室的同学们就是一个个就绪的线程,只有当老师点到名字的时候,这个同学才会答到。 - 运行状态(Running)
当处于就绪状态的一个线程被CPU调度时,这个线程就进入到了运行状态;只有处在就绪状态的线程才有可能进入到运行状态。 - 阻塞状态(Blocking)
阻塞状态主要分为等待阻塞、同步阻塞和其他阻塞。
(1)等待阻塞:当处于运行状态的线程执行wait()函数时,该线程会由运行状态变为等待阻塞状态;
(2)同步阻塞:当处于运行状态的线程获取synchronized同步锁失败时,线程会由运行状态变为同步阻塞状态;当处于等待阻塞的线程执行notify()函数或nottifyAll()函数或被其他线程唤醒会进入到同步阻塞状态。
当处于同步阻塞状态的线程获取到同步锁时,会进入到就绪状态,等待CPU的调度。
(3)其他阻塞:当处于运行状态的线程陷入IO中断或执行join()函数或执行sleep()睡眠函数时,会进入其他阻塞状态;当IO中断完毕或join()线程执行完毕或sleep()睡眠时间到,线程会由其他阻塞状态进入到就绪状态。 - 死亡状态(Dead)
当处于运行状态的线程执行run()方法结束或者异常退出的时,线程会由运行状态进入死亡状态。
二、线程与进程的区别
1.进程: 进程是具独立功能的在某个集合上的一次执行程序;进程是系统进行资源分配和调度的一个独立单位。
2. 线程:线程是进程内的一个执行实体或执行单元,是比进程更小的能独立运行的基本单位。
3. 两者的区别:
(1)操作系统引入线程机制后,进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位,资源分配给线程,线程只拥有很少的资源,线程切换代价比进程低。
(2)不同进程地址空间相对独立,同一进程内的线程共享同一地址空间,可以共享数据。一个进程的线程在另外一个进程内是不可见的。
(3)创建进程或者撤销进程,系统都要为之分配或者回收资源,操作系统开销远大于创建或撤销线程时的开销。
(4)系统在运行的时候会为每个进程分配不同的内存空间;而对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源。