文章目录
1.进程和线程的区别
进程是操作系统进行资源分配的基本单位,而线程是操作系统进行调度的基本单位,即CPU分配时间的单位 。
进程是一个独立的运行环境,而线程是在进程中执行的一个任务。他们两个本质的区别是是否单独占有内存地址空间及其它系统资源(比如I/O):
- 进程单独占有一定的内存地址空间,所以进程间存在内存隔离,数据是分开的,数据共享复杂但是同步简单,各个进程之间互不干扰;而线程共享所属进程占有的内存地址空间和资源,数据共享简单,但是同步复杂。
- 进程单独占有一定的内存地址空间,一个进程出现问题不会影响其他进程,不影响主程序的稳定性,可靠性高;一个线程崩溃可能影响整个程序的稳定性,可靠性较低。
- 进程单独占有一定的内存地址空间,进程的创建和销毁不仅需要保存寄存器和栈信息,还需要资源的分配回收以及页调度,开销较大;线程只需要保存寄存器和栈信息,开销较小。
2. 如何使用多线程
2.1Thread类和Runnable接口
首先,我们需要有一个“线程”类。JDK提供了Thread
类和Runnable
接口来让我们实现自己的“线程”类。
- 继承
Thread
类,并重写run
方法;其实Thread类也是实现了Runnable
接口的。 - 实现
Runnable
接口的run
方法;
2.2Thread类与Runnable接口的比较:
- 由于Java“单继承,多实现”的特性,Runnable接口使用起来比Thread更灵活。
- Runnable接口出现更符合面向对象,将线程单独进行对象的封装。
- Runnable接口出现,降低了线程对象和线程任务的耦合性。
- 如果使用线程时不需要使用Thread类的诸多方法,显然使用Runnable接口更为轻量。
所以,我们通常优先使用“实现Runnable
接口”这种方式来自定义线程类。
2.3 Callable、Future与FutureTask
通常来说,我们使用Runnable
和Thread
来创建一个新的线程。但是它们有一个弊端,就是run
方法是没有返回值的。而有时候我们希望开启一个线程去执行一个任务,并且这个任务执行完成后有一个返回值。
JDK提供了Callable
接口与Future
接口为我们解决这个问题,这也是所谓的“异步”模型。
2.3.1 Callable接口与Future接口
Callable
与Runnable
类似,同样是只有一个抽象方法的函数式接口。不同的是,Callable
提供的方法是有返回值的,而且支持泛型。Callable
一般是配合线程池工具ExecutorService
来使用的。ExecutorService
可以使用submit
方法来让一个Callable
接口执行。它会返回一个Future
,我们后续的程序可以通过这个Future
的get
方法得到结果。
2.3.2 FutureTask类
上面介绍了Future
接口。这个接口有一个实现类叫FutureTask
。FutureTask
是实现的RunnableFuture
接口的,而RunnableFuture
接口同时继承了Runnable
接口和Future
接口:
与Callable+Future搭配使用不同,FutureTask只需要创建一个对象,即可完成线程执行和结果接收。并且在很多高并发的环境下,有可能Callable和FutureTask会创建多次。FutureTask能够在高并发环境下确保任务只执行一次。这块有兴趣的同学可以参看FutureTask源码。
3.线程状态转换
3.1 操作系统中的线程状态转换
首先我们来看看操作系统中的线程状态转换。
在现在的操作系统中,线程是被视为轻量级进程的,所以操作系统线程的状态其实和操作系统进程的状态是一致的。
操作系统线程主要有以下三个状态:
-
就绪状态(ready):线程正在等待使用CPU,经调度程序调用之后可进入running状态。
-
执行状态(running):线程正在使用CPU。
-
等待状态(waiting): 线程经过等待事件的调用或者正在等待其他资源(如I/O)。
4.2 Java线程的6个状态
// Thread.State 源码
public enum State {
NEW, //处于NEW状态的线程此时尚未启动。这里的尚未启动指的是还没调用Thread实例的start()方法
RUNNABLE,//表示当前线程正在运行中。处于RUNNABLE状态的线程在Java虚拟机中运行,也有可能在等待CPU分配资源。
BLOCKED,//阻塞状态。处于BLOCKED状态的线程正等待锁的释放以进入同步区。
WAITING,//等待状态。处于等待状态的线程变成RUNNABLE状态需要其他线程唤醒。
TIMED_WAITING,//超时等待状态。线程等待一个具体的时间,时间到后会被自动唤醒。
TERMINATED;//终止状态。此时线程已执行完毕。
}