voliate 的实现原理
volatile可以保证线程可见性和禁止指令重排序,但是无法保证原子性。在JVM底层volatile是采用“内存屏障”来实现的。加入volatile关键字时,汇编后会多出一个lock前缀指令。lock前缀指令其实就相当于一个内存屏障。
Java 并发类库提供的线程池有哪几种?
Executors 目前提供了 5 种不同的线程池创建配置:
1)newCachedThreadPool():用来处理大量短时间工作任务的线程池。当无缓存线程可用时,就会创建新的工作线程;如果线程闲置的时间超过 60 秒,则被终止并移出缓存;其内部使用 SynchronousQueue 作为工作队列。
2)newFixedThreadPool(int nThreads),重用指定数目(nThreads)的线程,其背后使用的是无界的工作队列,任何时候最多有 nThreads 个工作线程是活动的。
3)newSingleThreadExecutor(),它的特点在于工作线程数目被限制为 1,操作一个无界的工作队列,所以它保证了所有任务的都是被顺序执行,最多会有一个任务处于活动状态
4)newSingleThreadScheduledExecutor() 和 newScheduledThreadPool(int corePoolSize),创建的是个 ScheduledExecutorService,可以进行定时或周期性的工作调度,区别在于单一工作线程还是多个工作线程。
5)newWorkStealingPool(int parallelism),Java 8 才加入这个创建方法,并行地处理任务,不保证处理顺序。
6)ThreadPoolExecutor():是最原始的线程池创建,上面1-3创建方式都是对ThreadPoolExecutor的封装。
线程池需要要的一些核心参数。
corePoolSize:基本线程数量
maximumPoolSize:最大线程数量。
keepAliveTime:空闲线程的存活时间 当实际线程数量超过corePoolSize时,若线程空闲的时间超过该值,就会被停止。
timeUnit:keepAliveTime的单位
runnableTaskQueue:任务队列 这是一个存放任务的阻塞队列,可以有如下几种选择:
ArrayBlockingQueue 由数组实现的阻塞队列,FIFO。
LinkedBlockingQueue 由链表实现的阻塞队列,FIFO。 fixedThreadPool使用的阻塞队列就是它。 它是一个无界队列。
SynchronousQueue 没有存储空间的阻塞队列,任务提交给它之后必须要交给一条工作线程处理;如果当前没有空闲的工作线程,则立即创建一条新的工作线程。 cachedThreadPool用的阻塞队列就是它。 它是一个无界队列。
PriorityBlockingQueue 优先权阻塞队列。
handler:饱和策略 当实际线程数达到maximumPoolSize,并且阻塞队列已满时,就会调用饱和策略。
AbortPolicy 默认。直接抛异常。 CallerRunsPolicy 只用调用者所在的线程执行任务。 DiscardOldestPolicy 丢弃任务队列中最久的任务。 DiscardPolicy 丢弃当前任务。