Android 面试之 Java 并发

在这里插入图片描述
Java 并发中考察频率较高的有线程、线程池、锁、线程间的等待和唤醒、线程特性和阻塞队列等。

线程

1. 线程的状态有哪些?
参考回答:

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

2. 线程中wait和sleep的区别?
参考回答:
wait方法既释放cpu,又释放锁。
sleep方法只释放cpu,但是不释放锁。

3. 线程和进程的区别?
参考回答:
线程是CPU调度的最小单位,一个进程中可以包含多个线程,在Android中,一个进程通常是一个App,App中会有一个主线程,主线程可以用来操作界面元素,如果有耗时的操作,必须开启子线程执行,不然会出现ANR,除此以外,进程间的数据是独立的,线程间的数据可以共享。

线程池

4. 与新建一个线程相比,线程池的特点?
参考回答:

  • 节省开销: 线程池中的线程可以重复利用。
  • 速度快:任务来了就能开始,省去创建线程的时间。
  • 线程可控:线程数量可空和任务可控。
  • 功能强大:可以定时和重复执行任务。

5. 线程池中的几个参数是什么意思,线程池的种类有哪些?
参考回答:
线程池的构造函数如下:

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
}

参数解释如下:

  • corePoolSize:核心线程数量,不会释放。
  • maximumPoolSize:允许使用的最大线程池数量,非核心线程数量,闲置时会释放。
  • keepAliveTime:闲置线程允许的最大闲置时间。
  • unit:闲置时间的单位。
  • workQueue:阻塞队列,不同的阻塞队列有不同的特性。

线程池分为四个类型:

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

7. 死锁触发的四大条件?
参考回答:

  • 互斥锁
  • 请求与保持
  • 不可剥夺
  • 循环的请求与等待

8. synchronized和Lock的区别?
参考回答:

  • synchronized是Java中的关键字,是Java的内置实现;Lock是Java中的接口。
  • synchronized遇到异常会释放锁;Lock需要在发生异常的时候调用成员方法Lock#unlock()方法。
  • synchronized是不可以中断的,Lock可中断。
  • synchronized不能去尝试获得锁,没有获得锁就会被阻塞; Lock可以去尝试获得锁,如果未获得可以尝试处理其他逻辑。
  • synchronized多线程效率不如Lock,不过Java在1.6以后已经对synchronized进行大量的优化,所以性能上来讲,其实差不了多少。

线程间通信

9. notify和notifyAll方法的区别?
参考回答:
notify随机唤醒一个线程,notifyAll唤醒所有等待的线程,让他们竞争锁。

10. volatile的原理?
参考回答:

  • 可见性
    如果对声明了volatile的变量进行写操作的时候,JVM会向处理器发送一条Lock前缀的指令,将这个变量所在缓存行的数据写入到系统内存。

多处理器的环境下,其他处理器的缓存还是旧的,为了保证各个处理器一致,会通过嗅探在总线上传播的数据来检测自己的数据是否过期,如果过期,会强制重新将系统内存的数据读取到处理器缓存。

  • 有序性
    Lock前缀的指令相当于一个内存栅栏,它确保指令排序的时候,不会把后面的指令拍到内存栅栏的前面,也不会把前面的指令排到内存栅栏的后面。

阻塞队列

11. ConcurrentHashMap的原理?
参考回答:
数据结构的实现跟HashMap一样,不做介绍。

JDK 1.8之前采用的是分段锁,核心类是一个Segment,Segment继承了ReentrantLock,每个Segment对象管理若干个桶,多个线程访问同一个元素的时候只能去竞争获取锁。

JDK 1.8采用了CAS + synchronized,插入键值对的时候如果当前桶中没有Node节点,使用CAS方式进行更新,如果有Node节点,则使用synchronized的方式进行更新。

猜你喜欢

转载自blog.csdn.net/duoduo_11011/article/details/106292478