1.多线程有哪4种实现方式?
常见的2种有:
- 继承Thread类、
- 实现Runnable接口、
不常见的2种:
- Callable接口、Future Task创建线程
- 通过线程池创建线程。优先使用ThreadPoolExecutor,不建议使用Executor。
2.Runnable以及Thread的联系和区别?
- Thread类,是Runnable接口的子类
- 使用Runnable,可避免Java继承的局限性
- Runnable适合于实现资源的共享、而Thread却不能
3.线程的状态有哪些?线程状态的使用场景是什么?
- 线程在它的生命周期中会处于不同的状态。Java线程状态,参考Thread内部枚举类State的源码。
public enum State{
new, //新建未start的线程状态new
Runnable, //运行中的线程状态
blocked, //等待锁的线程状态
WAITING, //调用wait、join且没设置超时的线程状态
TIMED_WAITING, //调用wait、join、sleep且没设置超时的线程状态
TERMINATED; //运行结束的线程状态
}
4.Runnable和Callable有什么不同?
- 二者都是接口。callable的方法是call()Runnable()方法是run()
- Callable的任务执行后可返回值。Runnable没有返回值
- call方法可以抛出异常、run方法不可以
- 运行Callable任务可以拿到一个Future对象
5.Java多线程中调用wait和sleep方法有什么不同?
- 所属对象不同。sleep属于Thread类的方法、wait属于Object类的方法
- 阻塞方法不同。sleep阻塞当前正在执行的进程、wait阻塞调用该对象的进程。
- 解除阻塞方法不同。sleep超时自动解除、wait需要notify/notifyAll唤醒
6.停止java线程有哪些常见的方法?
- 使用退出标志,使线程正常退出
- 使用interrupt方法终止线程
- 使用stop方法强行终止线程,是过去作废的方法。但不推荐
7.为何废弃Java中stop方法?stop方法有什么隐患
- 使用stop方法会强行终止线程的所有锁定,如果对象处于一种不连贯的状态,那么损坏的对象对其他线程可见。这有可能导致不安全的操作。
8.Thread类中的start()和run()方法有什么区别
- start方法起点线程,JVM自动调用该线程的run方法
- 创建线程时,启动线程会使run方法在那个独立执行的线程中被调用。
9.什么是线程安全?请说说有哪些线程安全的java集合类?
- 并发环境下,多个线程执行相同代码逻辑每次线程执行正确。
- Hashtable、Vetor、ConcurrentHashMap
10.什么是非线程安全?请说说有哪些线程不安全的java集合类?
- 多个线程相同的代码逻辑,每次线程的执行结果错误。
- HashMap、ArrayList、HashSet
11.在java中Executor和Executors的区别?
- Executor 接口对象能执行我们的线程任务;
- Executors 工具类的不同方法按照我们的需求创建了不同的线程池,来满足业务的需求。
- ExecutorService接口继承了Executor接口并进行了扩展,提供了更多的方法,我们能够获得任务执行的状态并且可以获取任务的返回值。
12.如何使用synchroinzed关键词?
- 1.方法声明时使用,放在范围操作符(public等)之后,返回类型声明(void等)之前
- 2.对某一代码块使用,synchronized后跟括号,括号里是变量
- 3.synchronized后面括号里是一对象,此时线程获得是对象锁
- 4.synchronized后面括号里是类,此时,线程获得的是对象锁
13.ReentrantLock和synchronized有何区别?
两者的共同点:
- 都是用来协调多线程对共享对象、变量的访问
- 都是可重入锁,同一线程可以多次获得同一个锁
- 都保证了可见性和互斥性
两者的不同点:
- ReentrantLock 显示的获得、释放锁,synchronized 隐式获得释放锁
- ReentrantLock 可响应中断、可轮回,synchronized 是不可以响应中断的,为处理锁的
不可用性提供了更高的灵活性 - ReentrantLock 是 API 级别的,synchronized 是 JVM 级别的
- ReentrantLock 可以实现公平锁
- ReentrantLock 通过 Condition 可以绑定多个条件
- 底层实现不一样, synchronized 是同步阻塞,使用的是悲观并发策略,lock 是同步非阻
塞,采用的是乐观并发策略 - Lock 是一个接口,而 synchronized 是 Java 中的关键字,synchronized 是内置的语言
实现。 - synchronized 在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;
而 Lock 在发生异常时,如果没有主动通过 unLock()去释放锁,则很可能造成死锁现象,
因此使用 Lock 时需要在 finally 块中释放锁。 - Lock 可以让等待锁的线程响应中断,而 synchronized 却不行,使用 synchronized 时,
等待的线程会一直等待下去,不能够响应中断。 - 通过 Lock 可以知道有没有成功获取锁,而 synchronized 却无法办到。
- Lock 可以提高多个线程进行读操作的效率,既就是实现读写锁等
14.CountDownLatch(闭锁)用于多线程的什么场景?
- 实现最大的并行性
- 开始执行前等待N个线程完成各自任务
- 死锁检测
15.有哪俩种方法实现多线程按照顺序执行?
- Thread的join()方法
- 使用jdk5推出的线程池Executors创建单例的方法
- CountDownLatch(倒计数)类
- CyclicBarrier(回环栅栏)类
- Sephmore(信号量)类
16.Collections和Collection有何区别?
- Collection是各种集合接口的父接口
- 继承Collection的接口有Set、List等等
- Collection提供了关于集合的删除、插入、遍历等操作
- Collections是集合类的一个工具类
- Collections不能被实例化、服务于Collection框架
- Collections包含实现对各种集合的搜索、排序、线程安全等相关操作
17.Java中Semaphore是什么?有何用途?
- Semaphore(信号量)。必须由获取它的线程释放、常用语限制可以访问某些资源的线程数量。
- Semaphore基于AQS。CAS设计。有俩种模式:公平模式和非公平模式。
- 公平模式:调用acquire顺序就是获取许可证的顺序,遵循FIFO
- 非公平模式:是抢占式,不遵循FIFO
使用场景
线程的并发限流
18.Java中用到的线程调度算法是什么?
- 对高优先级、使用优先调度抢占式策略
- 同优先级线程组成先进先出队列、使用时间片策略
19.ReadWriteLock有何用途?什么场景下可以考虑使用ReadWritelLock?
- 使用场景:对共享资源有读和写的操作的场景
- ReadWritelLock是读写锁的接口
- ReentrantReadWriteLock是ReadWriteLock的一种体现
- java并发包提供读写锁ReentrantReadWriteLock
- 俩个锁,一个是读操作相关的锁,称共享锁。一个写相关的锁,称独占锁
20.怎么理解无界队列和有界队列?使用无界队列需要注意什么?
- 有界队列:有固定大小的比例。
- 无界队列:没有设置固定大小的比例。这队列特点是:可以直接入列。直到溢出
- 使用无解队列,要注意是否有内存溢出
21.阻塞队列和非阻塞队列有何不同?
- 两种线程安全的队列:并发队列和阻塞队列
- 并发队列ConcurrentLinkedQueue采用CAS实现
- 阻塞队列,用阻塞算法实现。使用阻塞算法的队列可以使用同一个锁,或俩个锁方式实现
- 在queue基础上添加接口put、添加一个元素。如果队列满。则阻塞take。移除并返回队列头部元素。如果队列为空,则阻塞
- 非阻塞方法:添加接口add,如果队列已满。移除接口reove、如果队列为空,都会抛出异常。尽量不要使用非阻塞方法,否则容易出现意外错误。
- 在并发编程中,一般推荐使用阻塞队列。尽量避免出现意外错误。
22.请讲讲concurrent包有哪些重要的内容?
- AQS框架
- 非阻塞数据结构
- 原子变量类
- lock
- 同步器
- 阻塞队列
- 并发执行器
- 并发容器
23.Java中有哪些常见的原子操作类?底层实现原理是什么?
- 原子更新基本类型、原子更新数组、原子更新引用、原子更新字段
- 底层原理:Atomic包下原子操作类采用乐观锁策略CAS更新数据。
- 使用CAS鉴别线程是否冲突。出现冲突。重试当前操作知道没有冲突
24.如何实现多线程的异步编程?
Future类