安卓面试总结(4)——Java 多线程II

上一篇

安卓面试总结(3)——Java 多线程I

上一篇博客写到了多进程的一些东西,实际上都是我把我手写的内容一篇一篇写到博客上,为什么这么傻要做这种事情呢?因为问我希望我能在手机上方便地去阅读,每一篇博客的量都是一张 A4 纸的正反面,我觉得内容还是适中吧,不要说读者会看我的博文,更希望的是自己有机会可以去回顾。上次面试的时候光顾着看什么 IPC、消息机制、view 事件,被问到基础内容心里都蒙了一下,千里之行还是始于足下啊!

七、中断

中断:一个线程执行完毕后会自动结束,运行时发生异常也会提前结束

  1. InterruptedException

    • 通过调用一个线程的 interrupt() 来中断该线程,如果该线程处于阻塞、限期等待或者无限等待状态,那么就会抛出 InterruptedExceptedException,结束线程。
    • 注意不能中断 I/O 阻塞和 synchronized 锁阻塞(不然就异常了,冲入锁呢?JDK实现)
  2. interrupt():线程方法,标志中断位(仅此而已,阻塞等待抛异常)

  3. interrupted():判断线程是否处于中断状态

    如果线程的 run 方法执行一个无限循环,应该检查标志位来跳出循环

  4. 和 Executor 关系:

    • Executor 的 shutdown 会等待线程全执行完再关闭,而 shutdownNow() 会调用所有线程的 interrupt() 方法
    • 如果只想中断一个线程,可以用 submit 方法提交线程,使用返回的 Future<?> 来关闭,使用其 cancel 方法来中断线程。

八、互斥同步

  1. synchronized 由 JVM 实现(内置锁)

    • 同步一个代码块:只作用于同一个对象
    • 同步一个方法:同上
    • 同步一个类:作用于整个类,不同对象只需要同类,则同步代码生效
    • 同步一个静态方法:同上
  2. ReentrantLock(显示锁)由 JDK 实现

    优点:

    • 获取和释放的灵活性
    • 轮训锁和定时锁
    • 公平性

    ReentrantLock 方法:

    • lock()
    • tryLock()
    • tryLock(long timeout, TimeUnit)
    • unlock():注意在 finally 内释放锁
    • newCondition()

    比较

    • 实现方式不同
    • 性能,新 Java 对 synchronized 优化(如自选锁,性能大致相同)
    • ReentrantLock 可中断锁,synchronized 不行
    • ReentrantLock 可以是公平锁
    • ReentrantLock 可以绑定多个条件

    Condition 方法:

    • await()
    • await(long timeout, TimeUnit)
    • singnal()
    • singnalAll()
  3. 使用选择:优先使用 synchronized,JVM 支持不依赖 JDK,且不能被中断

  4. volatile

    • 保证此变量对所有线程可见,不能保证具有原子性(保存在内存)
    • 禁止指令重排(详细内容请看 JVM)
    • 读写性能几乎相同,写操作慢,需要加内存屏障

九、J.U.C-AQS 同步器

  1. CountDownLatch
    • 倒计时门栓:用来控制一个线程等待多个线程
    • 维护了一个计数器 cnt,每次调用 countDown() 会让计算器减1,减到 0 的时候,那些因为调用 CountDownLatch 的 await() 方法而在等待的线程就会被唤醒。
  2. CyclicBarrier
  • 障栅:用来控制多个线程互相等待,只有但多个线程都到达时,这些线程才会继续执行,
  • 可以 reset 循环使用
  • 维护计数器,执行 await 会减 1,并进行等待,知道计数器为 0,所有等待线程执行
  1. Semaphore
    • 信号量:可以控制对互斥资源的访问线程数
    • 创建时指定信号量数量,通过 acquire() 获取,获取数量有限,为得到要等待
    • 需要在 finally 里面 release
  2. 其他
    • Phaser:可变计数障栅
    • Exchanger:交换器(互相交换)
    • SynchronousQueue:同步队列,固定方向,size = 0

十、AysncTaask

  1. 创建异步线程更简单(必须在 UI 线程创建)
  2. 三个泛型(传入、传递、传出)
  3. 方法:
    • execute(…变长):执行
    • onPreExecute()、onProgressUpdate(UI线程)、onPostExecute
    • doInBackground(…):后台执行
  4. 原理分析(源码很复杂):
    • 有状态控制
    • 通过 Callable(mWorker)、Future、FutureTask(mFuture),交给异步线程执行
    • 通过 Handler 将数据传出

十一、内存模型三大特性

  1. 原子性
  2. 可见性
  3. 有序性

十二、线程安全

  1. 不可变(final)

  2. 互斥同步(锁)

  3. 非阻塞式同步

    • 解决现存阻塞和唤醒带来的性能问题

    • 锁的分类

      • 悲观锁:总是认为只要不去做正确的同步,就会出现问题
      • 乐观锁:先进行操作,如果没有其他线程争用共享数据,那就成功了,否则采取补偿措施(不断地重试,直到成功为止)
    • CAS:比较并交换(compare-and-swap)

      • 硬件支持两个步骤具有原子性
      • CAS 指令有三个操作数:内存地址 V、就旧预期值 A 和新值 B,只有到 V 的值等于 A,才将 V 的值更新为 B
    • 原子类操作

      • AtomocInteger 的方法调用了 Unsafe 类的 CAS 操作:xx.incrementAndGet()

      • LongAdder、LongAccumulator 只有当所有工作完成后再累加操作,减少重试次数

      • 原子类更新

        do {
            oldValue = largest.get();
            newValue = Math(oldValue, observed);
        }while(!largest.compareAndGet(oldVaule, newValue));
        
下一篇

安卓面试总结(5)——Java 虚拟机 I

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值