zoukankan      html  css  js  c++  java
  • 并发编程@并发编程高级


    * JDK多任务执行框架
    * Executor框架
    Executor是一个线程工厂,可以创建特定功能的线程池
    Executor创建线程池的方法:
    * newFixedThreadPool()
    创建一个【固定数量】的线程池,该线程池的线程数量始终不变
    * 当有一个任务提交时,若线程池中空闲,则立即执行,若没有,则会被暂缓在一个任务队列当中,等待由空闲的线程去执行
    * newSingleThreadPool()
    创建一个【只有一个线程】的线程池
    * 当有一个任务提交时,若线程池中空闲,则立即执行,若没有,则会被暂缓在一个任务队列当中,等待由空闲的线程去执行
    * newCacheThreadPool()
    创建一个【可以根据实际情况调整线程个数】的线程池,不限制最大线程数量
    * 当有一个任务提交时,若线程池中空闲,则立即执行,若没有,则会创建一个新的线程去执行。
    * 对于空闲的线程,超过60秒会自动回收
    * newScheduledThreadPool()
    创建一个SchededExecutorService对象,可以指定线程的数量
    备注:
    各种ThreadPool实际上都是new ThreadPoolExecutor()对象,只是根据传递参数的不同,导致它实例化出的线程池对象具有特定的功能
    * 自定义ThreadPool
    * 通过new ThreadPoolExecutor,传递特定参数可以创建自定义的线程池对象
    public ThreadPoolExecutor(
    int corePoolSize, // 当前核心线程数
    /* 对于jdk提供了线程池,初始化时就初始化的线程数。自定义的时候不会初始化 */

    int maximumPoolSize, // 最大线程数
    long keepAliveTime, // 线程空闲时保持活跃的时间
    TimeUnit unit, // 指定时间单位
    BlockingQueue<Runnable> workQueue // 指定缓冲队列,当线程都忙,可以将任务暂存
    ThreadFactory threadFactory, //
    RejectedExecutionHandler handler // 拒绝执行的方法
    ) {}
    * 这个方法对于队列是什么类型的比较关键:
    * 使用有界队列时,若有新的任务需要执行:
    若线程池实际线程数小于corePoolSize,则优先创建线程
    若线程池实际线程数大于corePoolSize:
    * 若队列未满,则会将任务加入队列,等由线程空闲的时候才执行
    * 若队列已满:
    * 若总线程数不大于maximumPoolSize,则创建线程去执行
    * 若总线程树大于maximumPoolSize,则执行拒绝策略
    * 使用无界队列时,LinkedBlockingQueue,除非系统资源耗尽,否则不会存在任务入队失败的情况。
    若线程池实际线程数小于corePoolSize,则创建线程
    若线程池实际线程数大于corePoolSize,则不再创建线程,如果此时还有任务,则加入等待队列
    * 拒绝策略
    AbortPolicy:直接抛出异常组织系统正常工作
    CallerRunsPolicy:只要线程池未关闭,该策略直接在调用者线程中,运行当前被丢弃的任务
    DiscardOldestPolicy:丢弃最老的一个请求,尝试再次提交当前的任务
    DiscardPolicy:丢弃无法处理的任务,不给予任何处理
    * 自定义拒绝策略
    实现RejectExecutionHandler接口

    * Concurrent.util工具包下常用【工具类】
    * CyclicBarrier
    假设由如下场景:每一个线程代表一个运动员,当运动员都准备好,才一起出发,只要由一个人每准备好,大家就都不出发
    * CountDownLatch(latch寄存器)
    它经常用于监听某些初始化操作,等初始化执行完毕后,通知主线程继续工作
    * CyclicBarrier和CountDownLatch的区别
    * CyclicBarrier是多个线程等待,多个线程通知,满足个数的话,多个线程执行各自的线程逻辑
    * CountDownLatch是一个线程等待,多个线程发出通知,满足个数的话,这个线程执行

    * 如何解决高并发【粗粒度进行分流、细粒度进行限流】
    * 服务器方面(分流)-- 粗粒度 备注:技术厉害的可以在nginx上进行限流
    * 业务上,根据模块划分,使用分布式
    * 技术上,使用nginx/lvs+haproxy搭集群,负载均衡(轮询),进行分流
    * Java技术方面(限流)-- 细粒度
    * 信号量进行限流
    * 线程池(高并发队列)
    * 高并发重入锁、读多写少读写锁
    * 其他
    * 使用缓存
    * 页面静态化
    * 文件系统存储图片资源等
    * 分表(避免多表查询)

    * 信号量(Semaphore)
    * 相关概念
    * PV:page view,网站总访问量
    * UV:unique visitor,每天中的客户访问量,一个客户ID一天内只记录一次
    * QPS:query per second,每秒查询数,即吞吐量
    * RT:response time,请求响应时间
    * 80/20原则:80%的访问请求将在20%的时间内达到
    * 一个系统的峰值
    * QPS = (总PV * 80%) / (60 * 60 * 24 * 20%)
    * Semaphore可以控制系统的流量:
    * 拿到信号量的线程可以进入,否则就等待。通过acquire()和release()获取和释放访问许可

    * 锁
    * ReentrantLock -> condition [await/signal]
    * Lock用法:
    * 锁的嗅探:
    * tryLock(): 尝试获得锁,获得结果用true、false返回
    * tryLock(): 在给定时间内尝试获得锁,获得结果用true、false返回
    * isFair(): 是否是公平锁
    * isLocked(): 是否锁定
    * getHoldCount(): 查询当前线程保持此锁的个数,也就是调用lock()的个数
    * lockInterruptibly():优先响应中断的锁
    * 公平锁、非公平锁
    Lock lock = new ReentrantLock(Boolean isFair);
    * 默认是非公平锁,false即非公平、true即公平
    *
    公平:先调用先上锁,有序[需要维护顺序,浪费性能]
    非公平:按CPU分配上锁,无序[效率更高]

    * 读写锁
    * ReentrantReadWriteLock
    * ReadWriteLock
    * ReadLock
    * ReadWriteLock
    * 核心就是实现读写分离的锁,在高并发、尤其是读多写少的情况下,性能远远高于ReentrantLock
    * 原则:读读共享、写写互斥、读写互斥
    * Lock比Synchronize有什么优势?
    * 1.8前,Lock性能比Synchronize好,1.8后,对synchronize进行优化
    * Lock必须在final中释放锁,它不会自动释放锁,而synchronize会自动释放锁
    * Lock更灵活,可以有多个condition来操作线程通信
    * 锁的优化总结
    * 避免死锁
    * 减少锁的持有时间
    * 减小锁的粒度
    * 锁的分离
    * 尽量使用无锁的操作,如原子操作(Atomic系列类),volatile关键字

  • 相关阅读:
    ehcache 2.4 即将发布,亮点多多
    2010 年个人回忆与总结
    ehcache 2.4 即将发布,亮点多多
    JBoss Seam 3.0.0.Beta1 发布
    JBoss Seam 3.0.0.Beta1 发布
    jQuery 1.5 正式版如期发布
    jQuery 1.5 正式版如期发布
    Contracts for Java
    2010 年个人回忆与总结
    Contracts for Java
  • 原文地址:https://www.cnblogs.com/qq438649499/p/12111781.html
Copyright © 2011-2022 走看看