《Java并发编程的艺术》总结
操作系统调度的最小单元是线程,也叫轻量级进程(LightWeight Process),在一个进程里可以创建多个线程,这些线程都拥有各自的计数器、堆栈和局部变量等属性,并且能够访问共享的内存变量。处理器在这些线程上高速切换,让使用者感觉到这些线程在同时执行。
为什么要使用多线程
- 更多的处理器核心
线程是大多数操作系统调度的基本单元,一个程序作为一个进程来运行,程序运行中会创建多个线程,而一个线程在某一时刻只能运行在一个处理器核心上
- 更快的响应时间
-
更好的编程模型
线程优先级
Java线程中,通过整型成员变量 priority 来控制优先级,优先级的范围为1~10 。在线程构建的时候,通过 setPriority() 方法来修改优先级,默认为5,优先级高的线程分配时间片的数量要高于优先级低的线程。
线程优先级不能作为程序正确性的依赖,因为操作系统可以完全不用理会Java线程对于优先级的设定。
线程状态
- new:初始状态,线程被构建,但还没有调用start()方法
- runnable:运行状态,Java线程将操作系统中的就绪和运行两种状态笼统地称为:“运行中”
- blocked:阻塞状态,表示线程阻塞于锁
- waiting:等待状态,表示线程进入等待状态,进入该状态表示当前线程需要等待其他线程做出一些特定动作(通知或者中断)
- time_waiting:超时等待状态,该状态不同于waiting,它可以在指定的时间自行返回
- terminated:终止状态,表示当前线程已经执行完毕
线程中start与run的区别
run():只是调用了一个普通方法,并没有启动另一个线程,程序会按照顺序去执行代码
start():重新开启一个线程,不必等待其他线程运行完毕,只要得到cup就会执行该线程
等待/通知机制
- notify():通知一个在对象上等待的线程,使其从 wait() 方法返回,而返回的前提是该线程获取到了对象的锁
- notifyAll():通知所有等待在该对象上的线程
- wait():调用该方法的线程进入waiting状态,只有等待另外的线程通知或者被中断才会返回,需要注意,调用wait() 方法后,会释放对象锁
- wait(long):超时等待一段时间,这里的参数时间为毫秒,也就是等待长达n毫秒,如果没有通知就超时返回
- wait(long, int):对于超市时间更细粒度的控制,可以达到纳秒
sleep与wait的区别
sleep是Thread的方法,wait是Object的方法。sleep不会导致锁行为的改变
Daemon线程
Daemon线程是一种支持型线程,因为它主要被用作程序中后台调度以及支持性工作。这意味着,当一个Java虚拟机中不存在非Daemon线程的时候,Java虚拟机将会退出。可以通过调用Thread.setDaemon(true)将线程设置为Daemon线程。
ThreadLocal的使用
ThreadLocal,即线程变量,是一个以ThreadLocal对象为键、任意对象为值的存储结构。这个结构被附带在线程上,也就是说一个线程可以根据一个ThreadLocal对象查询到绑定在这个线程上的一个值。
线程池技术
目的
- 降低资源消耗
- 提高响应速度
- 提高线程的可管理性
运行步骤
- 线程池判断核心线程池里的线程是否都在执行任务。如果不是,则创建一个新的工作线程来执行任务。如果核心线程池里的线程都在执行任务,则进入下个流程。
- 线程池判断工作队列是否已经满。如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果工作队列满了,则进入下个流程。
- 线程池判断线程池的线程是否都处于工作状态。如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务。
使用
new ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler);
new ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory);
- corePoolSize(线程池的基本大小)
- runnableTaskQueue(任务队列)
- ArrayBlockingQueue
- LinkedBlockingQueue
- SynchronousQueue
- SynchronousQueue
- maximumPoolSize(线程池最大数量)
- ThreadFactory:用于设置创建线程的工厂
- RejectedExecutionHandler(饱和策略)
- AbortPolicy:直接抛出异常
- CallerRunsPolicy:只用调用者所在线程来运行任务
- DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务
- DiscardPolicy:不处理,丢弃掉
- keepAliveTime(线程活动保持时间)
- TimeUnit(线程活动保持时间的单位)
补充知识:进程调度算法
- 先来先服务(FCFS)
- 最短作业优先(SJF)
- 基于优先权的调度算法(FPPS)
- 时间片轮转(RR)
- 多级队列调度(Multilevel feedback queue)