Fork me on GitHub

Android 线程和线程池

线程

线程安全:同步(多线程间访问数据一致性)是目的,互斥是手段

线程的状态有:

  • new:新创建的线程
  • Ready:准备就绪的线程,由于CPU分配的时间片的关系,此时的任务不在执行过程中。
  • Running:正在执行的任务
  • Block:被阻塞的任务
  • Time Waiting:计时等待的任务
  • Terminated:终止的任务
    image

线程创建

线程的创建本3中方式

  • 继承 Thread 类的方式
  • 实现 Runnable 接口的方式
  • 其他方式,本质还是Thread来创建
Thread的匿名类的方式来实现
匿名方式创建 Runnable 实现类,并重写 run 方法。
使用 Lambda 方式创建匿名 Runnable 实现类(JDK 8+)。
实现 Callable 接口的方式,和Future一起使用。
匿名内部类创建 Callable 的实现类,并重写 call 方法。

同步

同步阻塞

  • synchronized关键字
作用于代码块:需要自己指定加锁对象,锁对象包括对象本身、对象的Class和其他对象。对给定对象加锁,进入同步代码前要获取给定对象的锁。
直接作用于实例方法:相当于给当前实例加锁,进入同步代码块前要获得当前实例的锁。
直接作用于静态方法:相当于对当前类加锁,进入同步代码前要获取当前类的锁。
  • ReentrantLock 方法,可实现公平锁和费公平锁,Sync来实现NoFairSync和FairSync
  • ReentrantReadWriteLocK
  • 利用Java的通知等等机制,Object.wait()和还有Object.notify()。wait方法既释放cpu,又释放锁。 sleep方法只释放cpu,但是不释放锁。
  • Semaphore,Semaphore.acquire()和Semaphore.release()
  • CountDownLatch
  • CyclicBarrier

同步不阻塞

基于冲突检测的乐观并发策略,缺点 循环开销大;优点 比锁强大很多

  • CAS 乐观锁,AtomicInteger
  • AQS 即AbstractQueuedSynchronizer, 队列同步器,AQS的实现依赖内部的同步队列(FIFO双向队列)

不同步

  • ReentrantLock AQS队列
  • ThreadLocal

线程池

Android提供了四种常用的操作多线程的方式,分别是:

  1. Handler+Thread
  2. AsyncTask
  3. ThreadPoolExecutor
  4. IntentService

线程池

public ThreadPoolExecutor (
    int corePoolSize, // 核心线程数量
    int maximumPoolSize, // 最大线程数(核心线程数 + 临时线程数)
    long keepAliveTime, // 临时线程的最大空闲时间
    TimeUnit unit, // 时间单位(针对临时线程)
    BlockingQueue<Runnable> workQueue, // 任务队列
    ThreadFactory threadFactory, // 线程工厂(可以为线程起名字),线程池中的线程默认名称为pool-m-thread-n
    RejectedExecutionHandler handler // 拒绝策略
    ) 

任务队列workQueue

  • ArrayBlockingQueue: 基于数组结构的有界阻塞队列,按 FIFO 排序任务;
  • LinkedBlockingQueue: 基于链表结构的阻塞队列,按 FIFO 排序任务,吞吐量通常要高于 ArrayBlockingQueue;
  • SynchronousQueue: 一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于 LinkedBlockingQueue;
  • PriorityBlockingQueue: 具有优先级的无界阻塞队列;

拒绝策略handler

  • AbortPolicy: 直接抛出异常,默认策略;
  • CallerRunsPolicy: 用调用者所在的线程来执行任务;
  • DiscardOldestPolicy: 丢弃阻塞队列中靠最前的任务,并执行当前任务;
  • DiscardPolicy: 直接丢弃任务;

线程池分为四个类型:

  • CachedThreadPool:闲置线程超时会释放,没有闲置线程的情况下,每次都会创建新的线程。
  • FixedThreadPool:线程池只能存放指定数量的线程池,线程不会释放,可重复利用。
  • SingleThreadExecutor:单线程的线程池。
  • ScheduledThreadPool:可定时和重复执行的线程池。

多线程执行任务的流程

  1. 简而言之:
  2. 任务来了,优先考虑核心线程。
  3. 核心线程满了,进入阻塞队列。
  4. 阻塞队列满了,考虑非核心线程。
  5. 非核心线程满了,再触发拒绝任务。
    image
posted @ 2021-08-09 21:00  KevinAt2022  阅读(126)  评论(0)    收藏  举报