Java进阶JUC
Callable
为了其实例可能由另一个线程执行的类设计的。
- 可以有返回值
- 可以抛出异常
- 方法不同,run()/call()
启动需要到的适配类:FutureTask
细节:
- 有缓存
- 结果可能需要等待,会阻塞!
常用辅助工具类(必须要会)
CountDownLatch
允许一个或多个线程等待直到在其他线程中执行的一组操作完成的同步辅助。
原理:
countDownLatch.await();//等待计算器归零,然后在向下执行
每次有线程调用countDown()数量-1,假设计算器变为0,countDownLatch.await()就会被唤醒,继续执行!
类似于减法计数器
CyclicBarrler
允许一组线程全部等待彼此达到共同屏障点的同步辅助。
类似于加法计数器
Semaphore(信号量)
一个计数信号量。在概念上,信号量维持一组许可证。
原理:
semaphore.acquire();获得,假设如果已经满了,等待,等待被释放为止!
semaphore.release();释放,会将当前的信号量释放+1,然后唤醒等待的线程!
作用:多个共享资源互斥的使用!并发限流,控制最大的线程数!
读写锁
ReentrantReadWriteLock
A ReadWriteLock 维护一对关联的lock,一个用于只读操作,一个用于写入。read lock可以有多个阅读器线程同时进行,只要没有作者。write lock是独家的。
BlockingQueue四组API
方式 | 抛出异常 | 有返回值,不抛出异常 | 阻塞等待 | 超时等待 |
---|---|---|---|---|
添加 | add | offer() | put() | offer(,) |
移除 | remove | poll() | take() | poll(,) |
检测对首元素 | element | peek | - | - |
SynchronousQueue 同步队列
没有容量,进入一个元素,必须等待取出来之后,才能再往里面放一个元素!
线程池(重点)
线程池:三大方法、七大参数、四种拒绝策略
程序的运行本质:占用系统的资源!优化资源的使用!==>至有池化技术
线程池、连接池、内存池、对象池///… 创建、销毁。这是十分浪费资源
池化技术:事先准备好一些资源,有人要用,就来我这里拿,用完之后还给我。
线程池的好处:
- 降低资源的消耗
- 提高响应的速度
- 方便管理
线程复用、可以控制最大并发数、管理线程
三大方法:
Executors.newSingleThreadExecutor();//单个线程
Executors.newFixedThreadExecutor();//创建一个固定的线程池的大小
Executors.newCachedThreadExecutor();//可伸缩的,遇强则强,遇弱则弱
七大参数:
int corePoolSize,//核心线程池大小
int maximumPoolSize,//最大核心线程池大小
long keepAliveTime,//超时了没有人调用就会释放
TimeUnit unit,//超时单位
BlockingQueue workQueue,//阻塞队列
ThreadFactory threadFactory,//线程工厂,创建线程的,一般不用动
RejectedExecutionHandler handle//拒接策略
四种拒绝策略:
new ThreadPoolExecutor.AbortPolicy()//银行满了,还有人进来,不处理这个人的,抛出异常
new ThreadPoolExecutor.CallerRunsPolicy()//哪来的去哪里!
new ThreadPoolExecutor.DiscardPolicy()//队列满了,丢掉任务,不会抛出异常
new ThreadPoolExecutor.DiscardOldestPolicy()//队列满了,尝试去和最早的竞争,也不会抛出异常!
拓展:
池的最大的大小如何去设置?
了解:IO密集型,CPU密集型==>调优
- CPU密集型,几核就是几,可以保持CPU的效率最高!(Runtime,getRuntime().availableProcessors())
- IO密集型 ,大于判断程序中十分耗IO的线程