1. 什么是原子操作?在Java Concurrency API中有哪些原子类?
- 原子操作是值一个不受其他操作影响的操作任务单元, 原子操作是在多线程环境下避免数据不一致必须的手段.
int++
并不是一个原子操作, 所以当一个线程读取它的值并加1时, 另外一个线程有可能读到之前的值, 这就会银发错误.
为了解决这个问题, 必须保证增加操作是原子的, 在JDK 1.5之前我们可以使用同步技术来做到这一点. 到JDK1.5,java.util.concurrent.atomic
包提供了int
和long
类型的包装类, 他们可以自动的保证对于他们的操作是原子的并且不需要使用同步.
2. Java Concurrency API中的Lock接口是什么?对比同步它有什么优势?
-
Lock
接口比同步方法和同步块提供了更句扩展性的锁操作. 他们允许更灵活的结构, 可以有完全不同的性质, 并且可以支持多个相关类的条件对象.
它的优势有: - 可以使锁更公平
- 可以使线程在等待锁的时候响应终端
- 可以让线程尝试获取锁, 并在无法获取锁的时候立即返回或者等待一段时间
- 可以在不同的范围, 以不同的顺序获取和释放锁
3. 什么是Executors框架?
- Executors框架同
java.util.concurrent.Executor
接口在Java 5中被引用. Executor框架是一个根据一组执行策略的调用, 调度, 执行和控制的异步任务的框架. - 无限制的创建线程会引起应用程序内存溢出. 所以创建一个线程池是个更好的解决方案, 因为可以限制线程的数量并且可以回收再利用这些线程. 利用Executor框架可以非常方便的创建一个线程池.
4. 什么是阻塞队列? 如何使用阻塞队列来实现生产者-消费者模型?
-
java.util.concurrent.BlockingQueue
的特性是: 当队列是空的时, 从队列中获取或删除元素的操作将会被阻塞, 或者当队列是满的时, 往队列里添加元素的操作会被阻塞.
阻塞队列不接受空值(null
), 当你尝试向队列中添加空值的时候, 它会抛出NullPoniterException
.
阻塞队列的实现都是线程安全的, 所有查询方法都是原子的并且使用了内部所或者其他形式的并发控制.
BlockingQueue
接口是java collections框架的一部分, 主要用于实现生产者-消费者的问题
5. 什么是Callable和Future?
- Java 5 在concurrent包中引入了
java.util.concurrent.Callable
接口, 它和Runnable
接口很相似, 但它可以返回一个对象或者抛出一个异常.
Callable
接口使用泛型去定义它的返回类型.Executors
类提供了一些有用的方法去线程池中执行Callable
内的任务. 由于Callable
任务是并行的, 我们必须等待它返回的结果.java.util.concurrent.Future
对象为我们解决了这个问题. 在线程池提交Callable
任务后返回了一个Future
对象, 使用它我们可以知道Callable
任务的状态和得到Callable
返回的执行结果.Future
提供了get()
方法让我们可以等待Callable
结束并获取它的执行结果.
6. 什么是Future Task?
-
FutureTask
是Future
的一个基础实现, 我们可以将他同Executors
使用处理异步任务. 通常我们不需要使用FutureTask
类, 但当我们打算重写Future
接口的一些方法并保持原来基础的实现时, 它就变得非常有用 . 我们可以仅仅继承于它并重写我们需要的方法.
7. 什么是并发容器的实现?
- Java集合类都是fail-fast的, 这就意味着当集合被改变且一个线程在使用迭代器遍历集合的时候, 迭代器的
next()
方法将抛出ConcurrentModificationException
异常.
并发容器支持并发的遍历和并发的更新.
主要的类有ConcurrentHashMap
,CopyOnWriteArrayList``和
CopyOnWriteArraySet`.
8. Executors
类是什么?
-
Executors
为Executor
,ExecutorService
,ScheduledExecutorService
,ThreadFactory
和Callable
类提供了一些工具方法.
Executors
可以同于方便的创建线程池.