面试系列之线程池
java线程:java线程是一个重量级操作,他的底层是使用操作系统的指令创建线程,设计到内核态的操作,所以线程的创建和销毁都十分消耗性能。
java线程创建,new Thread() 需要可以新建一个java层面线程对象,调用它的start方法,就会通过本地方法start0,调用操作系统创建一个线程并且和java层面的线程对象绑定,进入就绪状态。获得cpu时间片以后调用线程图像传入的任务对象的run方法。
操作系统的线程状态采用五态模型:新建 、就绪 、运行、阻塞、销毁
java中对阻塞态的区分比较细:新建、就绪、运行、超时等待、等待、阻塞、销毁、
创建线程只能通过new Thread(),但是我们有多重创建任务的方法,实现RUnable、Callable等。区别在于Runable没有返回值而且不会抛出异常。callable通过和FutureTask一起使用,使用共享变量的方式,将子线程的结果和异常共享到父线程。
java线程的没有提供可靠的中断机制,而是才用中断标识,但是线程代码可以选择处理或者不处理
java线程协作:volition、wait/notify、
基本参数:
- int corePoolSize:核心线程数
- int maximumPoolSize:最大线程数
- long keepAliveTime:非核心线程数最大存活时间
- TimeUnit unit: 时间单位
- BlockingQueue workQueue: 等待队列
- ThreadFactory threadFactory:线程工厂
- RejectedExecutionHandler handler:拒绝策略 (实现RejectedExecutionHandler类)
addWorker
work.run()
从以上的源码可以看出,线程池的处理流程是,
优先创建核心线程处理,其次是放入阻塞队列,最后才是创建非核心线程处理。 这种顺序也会为了尽量利用核心线程。如果创建非核心线程的优先级大于入队,会出现核心线程空闲,队列为空的情况。
线程池在使用execute()和submit()时,区别在于,使用execute时直接将任务放入work中,使用submit会先将任务封装到FutureTask中,再将FutureTask放到work中。
FutureTask将call方法的返回值存入outcome