Java并发基础

一. 同步器

1. synchronized

  • 互斥锁, 可重入锁(锁标志位+n),非公平锁
  • 保证原子性、可见性
  • 锁定的是堆中的对象,锁定this对象、Class对象.避免锁定对象改变
  • 写加锁,读不加锁=》脏读
  • 死锁。四大条件同时成立时
  • 异常时锁会自动释放
  • 不要用字符串常量作锁定对象
String s1 = "a";
String s2 = "a";
synchronized(s1)
syschronized(s2)
s1 s2则时同一把锁

2. volatile

  • 保证可见性、不保证原子性
  • JMM原理
  • 效率高,特殊场景使用

3. 原子类

  • AtomicInteger、AtomicBoolean AtomicReference等等
  • CAS实现
  • 代替简单的基本数据类型操作:(i++)
  • 多个原子方法组合不具备原子性
  • 比synchronized高效
  • 具有可见性

4. wait、notify/notifyAll

  • wait会释放锁,notify不会释放锁

5. CountDownLatch

  • CountDownLatch(n)指定门闩锁定次数
  • countDownLatch = 0释放锁
  • latch.wait
  • latch.countDown

6. ReentrantLock

  • 重入锁
  • 可以tryLock,可选超时参数
  • 被打断锁,在lock.lockInterruptibly()时
  • 可指定为公平锁:new ReentrantLock(true),默认不公平

7. Lock Condition

  • await、signal/signalAll

ThreadLocal

  • 线程间变量不相互影响,维护各自变量副本
  • 造成内存泄漏: ThreadLocal变量未清除,确保使用完remove()

二. 并发容器

单例模式

  • 线程安全的单例模式
    a. 内部类实现(不加锁,懒加载)
    b. 双锁检测(DCL)

1. 普通容器Set/Map(线程不安全)

HashSet
HashMap
TreeMap
LinkedHashMap
...

2. 并发量一般容器Set/Map

HashTable(锁住整个容器)
Collections.synchronizeXXX(将未加锁容器包装成加锁容器)
...

3. 高并发容器 Set/Map

  • ConcurrentHashMap (分段锁 16段)
  • ConcurrentSkipListMap 排序

List

1. 线程不安全

  • ArrayList
  • LinkedList
  • ...

2. 并发量一般

  • Collections.synchronizeXXX

3. 高并发

  • CopyOnWriteArrayList 读多写少

Queue(Deque 双端队列)

1. 并发队列

  • ConcurrentLinkedQueue

2. 阻塞队列

put时满了阻塞,take时空了阻塞

  • LinkedBlockingQueue
  • ArrayBlockingQueue
  • TransferQueue
    调用transfer()时,生产者直接发送给消费者
  • SynchronusQueue
    容量为0的TransferQueue,必须有消费者消费

3. 延迟队列

DelayQueue 等待时间长的先取出(适合定时任务)

三. 线程池

基础

  • Executor
  • ExecutorService submit()
  • Executors
  • Callable =有返回值的Runnable
  • FurtherTask 包装Callable
  • Further泛型接口 接收返回值get方法阻塞
  • ThreadPoolExecutor类

ThreadPool类型

  • fixedThreadPool
    1.可控制线程最大并发数(同时执行的线程数)
    2.超出的线程会在队列中等待

  • cachedThreadPool 推荐
    1.线程数无限制
    2.有空闲线程则复用空闲线程,若无空闲线程则新建线程 一定程序减少频繁创建/销毁线程,减少系统开销
    3.默认60s关闭空闲线程

  • singleThreadExecutor
    1.有且仅有一个工作线程执行任务
    2.所有任务按照指定顺序执行,即遵循队列的FIFO规则

  • scheduledThreadPool
    1.定时线程池。
    2.支持定时及周期性任务执行

  • workstealingPool
    0.工作窃取线程池
    1.daemon线程
    2.默认启动Cpu个数的线程

  • forkJoinPool
    可以继承下面的类实现:
    RecursiveAction:用于没有返回结果的任务。
    RecursiveTask :用于有返回结果的任务。

PStream API

执行的策略

  1. 线程数量未达到corePoolSize,则新建一个线程(核心线程)执行任务
  2. 线程数量达到了corePools,则将任务移入队列等待
  3. 队列已满,新建线程(非核心线程)执行任务
  4. 队列已满,总线程数又达到了maximumPoolSize,就会由(RejectedExecutionHandler)抛出异常

新建线程 -> 达到核心数 -> 加入队列 -> 新建线程(非核心) -> 达到最大数 -> 触发拒绝策略

拒绝策略

  1. 直接丢弃(DiscardPolicy)
    不执行新任务,也不抛出异常,基本上为静默模式。
  2. 丢弃队列中最老的任务(DiscardOldestPolicy)。
    将消息队列中的第一个任务替换为当前新进来的任务执行
  3. 抛异常(AbortPolicy)
    不执行新任务,直接抛出异常,提示线程池已满,线程池默认策略
  4. 将任务分给调用线程来执行(CallerRunsPolicy)。
    拒绝新任务进入,如果该线程池还没有被关闭,那么这个新的任务在执行线程中被调用

你可能感兴趣的:(Java并发基础)