多线程
- 线程的创建过程
Thread.run()->javaThread->系统线程->osThread->stack->TLAB->启动->Thread.run()(或等待)->结束
- 多线程执行遇到的问题
- 竞态条件:多个线程竞争同一资源时,如果对资源的访问顺序敏感,就称存在竞态条件,导致竞态条件发生的代码区,称为临界区
- 临界条件
- 共享与同步
- 多线程
线程池
- Excutor :执行者-顶层接口
- ExcutorService:接口api
- ThreadFactory:线程工厂-创建一批工厂
- Excutors:工具类
线程池参数
一、 缓存队列
- ArrayBlockingQueue:规定大小的 BlockingQueue
- LinkedBlockingQueue:大小不固定的 BlockingQueue
- PriorityBlockingQueue:类似于 LinkedBlockingQueue:可以自定义排序
- SynchronizedQueue:特殊的 BlockingQueue
二、 拒接策略. - ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出 RejectedExecutionException异常。(默认)
- ThreadPoolExecutor.DiscardPolicy:丢弃任务,但是不抛出异常。
- ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新提交被拒绝的任务
- ThreadPoolExecutor.CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务
三、ThreadFactory - 实现newThread方法,可以在创建线程时自定义线程的参数
创建线程池方法 (Executors)
- newSingleThreadExecutor:创建一个单线程的线程池,和普通单线程相比,signThread会将任务放到队列中去,如果此线程抛异常,则会有新的线程代替它继续执行queue
- newFixedThreadPool:固定大小线程池,每提交一个任务就创建一个线程,如果超出限制,则放入队列。该队列无限大
- newCachedThreadPool:可缓存线程池,会检测线程池中的线程是否活跃,如果超过60s则会将此线程执行其他任务。
- newScheduledThreadPool:多用于周期性的执行任务需求
- 线程池的大小不是越大越好,如果是cpu密集型,测线程池大小设置为cpu线程数+1,如果是io密集型线程池的大小设置为cpu*2+2.
Thread接口
Callable
- call() —有返回值
Future
锁
为什么要显示的加一个锁:
- synchronized,不够灵活,不可以用条件去加锁
- locl可以决定锁多久,可以有时间限定
- 决定其他线程遇到锁时,lock可以做决策
Lock
并发包
并发工具类的作用
- 需要控制实际并发访问的资源的并发数量
- 需要多个线程在某个时间同时开始运行
- 需要指定数量线程达到某个状态再继续处理
并发工具类
- Semaphore --信号量
- CountdownLatch 减法计数,计算为0时释放所有等待的线程。调用countDown()方法计数-1,调用await()方法只进行阻塞,对计数没有任何影响。各个子线程执行完成后汇聚和在await()所在主线程
- CyclicBarrier --加法计数,计数达到指定值时释放所有等待线程。计数达到指定值时,计数置为0重新开始。调用await()方法计数+1,若+1后的值不等于构造方法的值,则线程阻塞。await()是在各个子线程中,聚合点是在new CyclicBarrier的参数thread中
List线程安全的简单办法
- ArrayList的方法加synchronized
- Cllection.synchronizedList,强制将List的操作加上同步
- Arrays.asList,不允许删除,但是可以set替换元素
- Collections.unmodifiableList,不允许修改内容,包括添加删除