线程
java并发之volatile
volatile的属性特点是可见性,保存有序性,不保证原子性
可见性每个线程都有自己的cou别的线程无法访问
单例模式下的volatile确保单例对象返回的正确性
java并发之AQS
核心方法是acquire和release,
acquire当同步器状态不允熙获取操作时,当前线程不在队列中,则把它插入队列阻塞当前线程,如果在队列中,则移出队列
release是更新同步器状态,新的状态允许某个被阻塞的线程获取成功,解除队列中一个或多个线程的阻塞状态
Java并发之threadloca
作用是提供线程内的局部变量,这种线程在多线程访问下能够保证各线程里变量的独立性
定义:提供线程的局部变量,使线程中的某个值与保存值的对象关联起来
threadlocalmap是一个自定义的哈西映射,仅用于维护本地变量值,threadlocamap是teradloca的一个内部类,主要是有一个entry数组,entry数组的key是threadlocal,value值是threadloca对应的值,每个线程都有一个threadlocamap类型的threadloces变量
java并发之线程池
线程池的作用用来控制系统中某一任务运行时的线程的数量,护理过程中将任务放入队列,然后在线程创建后启动这些任务,如果工作线程的数量超过线程池的最大数量,那吗超过数量的线程在队列中排队等候,等待其他线程执行完毕,再从队列中取出任务执行。
线程池的七个参数:corePoolSize 线程池核心线程大小 maximumPoolSize 线程池最大线程数量 keepAliveTime 空闲线程存活时间 workQueue 工作队列 threadFactory 线程工厂
handler 拒绝策略
线程池的特点:
控制最大线程数,管理线程,线程复用
线程池的构造:
线程池管理器:用于创建管理线程池
工作线程:线程中执行任务的线程
任务:每个任务必须实现runnable接口,这样才能被线程池调用
任务队列:用于存放代处理的任务,通常是阻塞队列
线程池的实现;
ava中的线程池是通过Executor框架实现的,包含了Executor、Executors、ExecutorService、ThreadPoolExecutor、Callable和Future、FutureTask等。
ThreadPoolExecutor对象的属性
corepoolsize:线程池的核心线程数
maximumpoolsize:线程池的最大线程数
leepalivetime:线程空闲的存活时间,当线程超过corepoolsize时,多余空闲线程的存活时间,即多长时间被会被销毁
workqueue:任务中,用来保存尚未被执行的线程
threadfoury:线程工厂,用来创建线程
handel:拒绝策略当任务来不及处理时,用来拒绝任务
线程池的原理:
线程初始创建时,线程池中是没有线程的,当提交一个任务,线程池会创建一个线程, 当线程提交大于核心线程数量时,继续提交的任务会保存到阻塞线程里面,等待被执行,如果线程调用prstaretalloretreads这个方法时,线程池会提前创建并启用所有的核心线程,继续提交任务,如果阻塞线程也满了,如果小于最大线程数,那吗会继续创建线程来完成任务,如果大于最大线程数,那么需要拒绝策略来拒绝提交的线程,如果线程没有任务可以做,那么线程池所有的任务完成后会收缩到核心线程数的大小
线程池的拒绝策略
直接抛异常,拒绝系统的运行
直接在调用者线程中运行当前被抛弃的任务
丢弃即将被执行的任务,并且再次提交当前任务
丢弃当前任务不做任何处理
自定义一个拒绝请求接口,打印日志,并发送警报
java中的四种线程池
创建一个固定线程数量的线程池:其中核心线程池的数量等于最大线程的数量,使用LinkedBlockingQueue阻塞队列,当没有任务执行时,线程也不会被释放
创建一个可以缓存线程的线程池:使用SynchronousQueue阻塞队列,其中线程的数量可以达到最大线程数,当提交任务时,会重用以前的线程,如果没有线程可用会创建新的线程使用,如果一个线程空闲时间太长,则会回收线程,因此长时间保存空闲的线程也不会占用任何资源,适用于很多短期的任务场景
创建一个线程池可以在延后执行任务或定时执行任务
创建一个单线程的线程池:内部使用LinkedBlockingQueue阻塞队列,如果该线程异常结束,会继续创建一个新的线程执行这个任务,唯一的线程可以保证任务的顺序执行
阻塞队列:
ArrayBlockingQueue:由数组结构实现的有界阻塞队列,元素按照先进先出的元素排序,初始化时必须指定队列容量,默认情况下不保证公平的访问队列,也就是说在阻塞线程中不按照阻塞的顺序访问队列,
LinkedBlockingQueue:基于链表的阻塞队列:元素按照先进先出的元素顺序,初始化时如果不置顶容量,则按照最大的线程数来制定队列容量,性能比ArrayBlockingQueue高,因为对于生产者和消费者分别采用了独立的锁来控制数据的同步,在高并发时,生产者和消费者可以并行的操作队列中的数据,以此来提高整个队列的并发性
SynchronousQueue:不储存元素的阻塞队列,默认是非公平的,可以在初始化的时候制定公平性,每一个put操作必须等待一个take操作,否则不能继续添加元素,SynchronousQueue是负责把生产者处理的数据传递给消费者线程,本身不保存元素,吞吐量大于ArrayBlockingQueue和LinkedBlockingQueue
DelayQueue:是一个支持延迟获取元素的无界阻塞队列,队列使用PriorityQueue来实现,队列中的元素必须实现Delayed接口,在创建队列时可以指定多久从队列中获取元素,只有在延迟期满时才能从队列中获取元素主要应用在缓存设计,和定时任务的调度
LinkedTranferQueue:有链表组成的无界tranferQueue队列, 相对于其他队列来说增加了trytranfer和tranfer方法
LinkedBlockingDeque;是由链表组成的双端阻塞队列,可以从队列的两端插入或移出元素
常用的开启线程方法:继承Thread类,调用Runnable,Callable
Runnable和Callable都代表那些要在不同的线程中执行的任务。Runnable从JDK1.0开始就有了,Callable是在JDK1.5增加的。
他们的主要区别是Callable的call()方法可以返回值和抛出异常,而Runnable的run()方法没有这些功能。Callable可以返回装载有计算结果的Future对象。