一、进程和线程的
进程是操作系统的运行单元,会独立给进程分配资源,可以理解为操作系统的一个单独执行的程序。线程是任务执行单元依赖于进程而存在,同一进程的多线程可以共享内存数据。
并发编程
并发编程的特点就是通过多线程的技术将CPU的性能发挥到极致,提升系统性能,高并发的系统开发并发编程会显得尤为重要。并发编程会遇到的问题:内存泄露(内存没有办法被回收),线程安全,死锁。
二、并发编程的三要素:
原子性,可见性(一个线程对共享变量的修改另一个变量能看到),有序性
线程的生命周期
生成线程的4种方式:
- 继承Thread类
- 实现Runnable接口
- 通过ExecutorService 和Callable<Class> 实现有返回值的线程
第一步: 实现Callable 接口创建MyCallable 线程
第二步: 创建一个固定大小为5的线程池
第三步: 创建多个有返回值的任务列表list
第四步:创建一个有返回值的线程实例
第五步: 提交线程,获取Future 对象并将其保存到Future list中
第六步: 关闭线程,等待线程执行结束
第七步:遍历所有线程的运行结果
- 基于线程池创建线程。
三、5个常用的线程
newCachedThreadPool 可缓存的线程池
newFixedThreadPool 固定大小的线程池
newScheduledThreadPool 做任务调度的线程池
newSingleThreadExecutor 单个线程的线程池
newWorkStealingPool 足够大小的线程池(jdk 1.8)
举例使用方式:
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
四、线程的6个基本方法:
wait notify interrupt notifyAll sleep join yield
wait 方法进入阻塞状态,释放线程锁,所以被唤醒后不能直接进入就绪状态
sleep 会进入休眠,不会释放锁,醒来之后会立刻进入就绪状态。
yield 让出cpu资源进入就绪状态
interrupt 不会改变线程的实际状况,只会改变线程状态
join 在一个线程里调用join当前线程会进入阻塞状态会等待另一个线程运行完成之后再进入就绪状态
start 方法和run方法的区别
run 是线程执行体,而start是调用系统线程执行run方法。
- 多线程的锁
悲观锁和乐观锁
乐观锁认为每次读取过程中数据不会发生改变,而在更新的时候会判断别人是否更新数据
悲观锁每一次操作数据都会认为别人会对数据修改,所以每次读取数据都会上锁(Synchronized就是悲观锁)