程序、进程、线程
程序
程序是「静态」的,存放在硬盘中的可执行文件,包括「代码指令」和「数据」
进程
进程是「运行中的程序」,是程序的一次启动和执行:操作系统从磁盘载入程序到内存,分配必要的资源,开始运行程序的指令
进程的组成:「代码段」,「数据段」,「PCB」(id,name,status,priority,物理地址,context,file,others)(描述信息,调度信息,资源信息,上下文)
线程
线程是“进程代码段”的一段「执行流程」
线程的组成:「PC」,「栈内存」(方法的调用和返回对应了栈帧的入栈和出栈),「线程基本信息」(id,name,status,priority,others)
进程和线程的区别
- 一个进程至少有一个线程
- 线程之间共享同一块地址空间(方法去内存,堆内存),打开的文件和其他资源,故上下文切换速度较快
- 调度执行的基本单位:线程
- 资源分配的基本单位:进程
Thread
in Java
Thread
类
public void start()
用来启动一个线程,当调用start()
方法后,JVM才会开启一个新的线程来执行用户定义的线程代码逻辑,在这个过程中会为相应的线程分配需要的资源
public void run()
是线程代码的逻辑入口,不是给用户程序来调用的,当调用start()
方法之后,只要该线程获得了CPU时间片,就会执行run()
方法
创建一个空线程
1 | java复制代码public class Nov29 { |
Thread
类中,由于target
对象为null
,run()
方法什么也没做就结束了
1 | typescript复制代码@Override |
继承Thread
类
- 继承
Thread
类 - 重写
run()
方法
1 | java复制代码public class FirstThread extends Thread{ |
1 | java复制代码public class Nov29 { |
实现Runnable
接口
- 定义一个类实现
Runnable
接口 - 实现
run()
方法 - 通过
Thread
类的构造方法public Thread(Runnable target)
传入该类
函数式接口:有且仅有一个方法的接口
1 | java复制代码public class SecondThread implements Runnable{ |
1 | java复制代码public class Nov29 { |
对比:
- 通过继承
Thread
类来创建线程,可以直接使用Thread
类的实例的方法 - 实现
Runnable
接口来创建线程则不能直接调用Thread
类的实例的方法,需要通过Thread
类的静态方法public Thread currentThread()
来获取当前类 - 在实际开发中,由于Java不允许多继承,所以一般使用实现
Runnable
接口的方法来创建线程 - 通过实现
Runnable
接口的方法来创建线程能更好地实现数据和逻辑的分离 Thread
继承了Runnable
接口,其中的run()
方法无返回值,若需要异步获取程序的执行结构,应该采用实现Callable
的方式
数据和逻辑的分离
todo:这个不太理解,之后需要细看
匿名内部类
1 | java复制代码public class ThirdThread { |
1 | java复制代码class ThirdThread { |
Lambda表达式
一行代码搞定
1 | java复制代码public class Nov29 { |
实现Callable
接口
1 | java复制代码public class FourthThread { |
使用线程池
不推荐使用 Executors
创建线程池
1 | java复制代码public class ThreadPool { |
execute()
,无返回值,参数只能是Runnable
实现类,不能异步控制只能等其自动停止submit()
,有返回值,参数可以是有返回值的Callable
实现类,可以异步控制
Java线程原理
Java线程和操作系统线程
Java虚拟机把Java线程一对一映射到操作系统线程,线程的调度交给操作系统
在JVM看来,操作系统视角下的 running
状态和 ready
状态统一称为 runnable
状态
优先级
Java线程具有优先级,优先级高的获得调度机会统计规律上大于优先级低的线程,但不绝对
生命周期
1 | java复制代码public enum State { |
Java线程基本操作
操作
- sleep:使线程休眠
- yield:让出CPU时间片,让操作系统重新调度一次
- interrupt:将线程状态设置为中断,不会像
stop()
方法那样中止一个线程,线程状态设置为中断后线程自己判断是继续执行还是终止 - join:合并两个线程,让其中一个等待另一个执行完毕再执行;或者设置一个时间,时间到了就不等了
- daemon:守护线程(为用户进程提供服务的进程,与用户进程的关系是和JVM线程的关系一个是主动一个是被动)
调试
1 | sh复制代码➜ ~ jps |
本文转载自: 掘金