并发
一、线程和进程(JVM)
-
进程是程序的一次执行过程,是系统运行程序的基本单位,系统运行一个程序就是,就是一个进程的创建,运行到消亡
-
线程是相比进程更小的执行单位,一个进程在执行期间包含多个线程,多个线程之间共享堆和方法区
每个线程都独立的拥有自己的虚拟机栈、本地方法栈和程序计数器
二、 程序计数器为什么是私有的
(1)程序计数器的作用
- 字节码解释器通过改变程序计数器来依次读取命令,实现程序的顺序执行,循环、选择、异常处理
- 在多线程的情况下,使用程序计数器来记录当前程序执行的位置,等到程序放回来继续执行的时候,java代码知道程序从哪里继续执行
三、 虚拟机栈和本地方法栈为什么是私有的
(1)虚拟机栈
- 每个java方法在执行的同时会创建一个栈帧,来保存局部变量表、操作数栈,常量池引用等。从方法的调用直到方法的结束调用过程,就对应着一个栈帧从虚拟机栈从入栈出栈的过程
(2)本地方法栈
- 和虚拟机栈的主要功能类似,一个是为了执行java方法服务,一个是为了执行本地的native方法服务。
(3)私有的原因
- 由于不同线程的局部变量不想被其他线程访问到,所以需要本地机栈和虚拟机栈私有
四、 什么是堆、方法区
- 堆是内存中最大的一块区域,主要是为了保存新创建的对象
- 方法区是保存已经被加载的类的信息、静态变量和常量
五、 sleep()和wait的区别和共同点
- 两者的主要区别:sleep()不会释放锁,wait()会释放锁
- 都可以使得程序暂停
- wait一般用于多线程之间交互,sleep()用于一个线程的暂停使用
- wait()使用后需要使用一个对象上的notify()去唤醒或者是notifyAll(),sleep在定时时间到之后会自动醒来
六、 volatile关键字
- 并发编程的三大特性:原子性、有序性、可见性
- volatile可以保证有序性和可见性(实现synchronized关键字的有序性和可见性)
七、 synchronized和volatile的区别
-
synchronized可以保证数据的原子性,但是后者不可以
-
synchronized是重量级的锁,其底层的可见性和有序性也是volatile保证的,一般可以使用volatile的就是用
-
volatile实现多线程之间数据的可见性,只能修饰变量
synchronized可以修饰变量、方法和代码块
八、为什么要使用线程池技术
(1)为什么需要这个技术
- 降低资源的损耗:创建和销毁一个线程的代价比较高
- 提高响应速度: 任务到达时不需要时间去创建线程
- 提高线程的可管理性: 线程可以统一的监控和管理
(2)实现Runnable接口和Callable的区别
- 前者没有返回值和异常,后者有
- Executors工具类有直接可以在两者之间进行转换
(3)执行execute()和submit()方法区别
- 之前没有返回值,不知道任务是不是成功
- 后者有返回值,可以知道任务的运行状态,返回的Future对象,可以通过这个对象判断是否成功。
(4) 怎么创建一个线程
- 使用ThreadPoolExecutor创建
- FixedThreadPool 创建固定数量的
- SingleThreadExecutor 创建单个线程 其余的在队列中等待
- CacheThreadPool 创建数量不确定,不够的时候就创建,创建后加入线程池,等待复用
参考文章:Java Guide