一、线程和进程的区别
进程是正在运行程序的实例,进程中包含了线程,每个线程执行不同的任务
不同的进程使用不用的内存空间,在当前进程下的所有线程可以共享内存空间
线程更清凉,线程上下文切换成本一般比进程上下文切换低
二、并行和并发的区别
并发是同一时间应对多件事情的能力
并行是同一时间动手做多件事情的能力
三、创建线程的方式
1.继承Thread类,重写run方法,使用的时候先new 一个继承Thread的对象,然后执行start方法。
2.实现Runable接口,重写run方法,创建实现Runable的对象,new 一个Thread,将对象放入,执行start方法。
3.实现callable接口。
4.使用线程池。
四、Runable和Callable区别
1.Runnable接口run方法没有返回值。
2.Callable接口call方法有返回值,是个泛型,和Future、FutureTask配合可以用来获取异步执行的结果。
3.Callable接口的call允许跑出异常。
五、run和start方法的区别
1.start:用来启动线程,通过该线程调用run方法执行run方法中所定义的逻辑代码。start只能被调用一次。
2.run:封装了要被执行的代码。只是一个普通方法。
六、线程的几种状态
1.NEW(新建状态)线程刚被创建出来
2.RUNNABLE(可执行状态)执行了start方法
3.BLOCKED(阻塞状态)加锁的情况下无法获得锁
4.WAITING(等待状态)执行了wait方法
5.TIMED_WAITING(计时等待状态)执行了sleep方法
6.TERMINATED(死亡状态)线程执行完毕
七、如何保证线程顺序执行
可以使用线程中的join方法,等待上一个线程运行结束
八、notify和notifyAll有什么区别
notifyAll:唤醒所有等待的线程
notigy:只随机唤醒一个等待线程
九、wait和sleep的区别
相同点:都是让线程进入阻塞状态
区别:
1.方法归属不同
sleep是Thread方法
wait是Object的方法
2.醒来的时机不同
wait()如果不唤醒就会一直等待下去
3.锁特性不同
wait执行后会释放锁,允许其他线程获得锁,sleep不会释放锁。
十、如何停止一个正在运行的线程
使用退出标志,让线程正常退出
执行使用stop方法退出
使用interrupt方法中断线程
十一、synchronized底层原理
Synchronized采用互斥的方式让同一时刻至多只有一个线程能够持有。
底层是由monitor实现的,monitor是jvm级别的对象(C++实现),线程获得锁需要使用对象关联monitor。
在monitor内部有三个属性,owner、entryList、waitset。
其中owner是关联的获得锁的线程,并且只能有一个线程,已经关联之后,别的线程进入就会去entryList里面进行等待,waitset是执行了wait方法之后处于waiting状态的线程等待。
十二、谈一下JMM
JMM是java内存模型,定义了共享内存中多线程程序读写操作的行为规范,通过这些规则来规范对内存的读写操作从而保证指令的正确性。
JMM把内存分为两块,一块是私有线程的工作区域,一块是所有线程的共享区域。
线程和线程之间是相互隔离的,线程和线程之间交互需要通过主内存。
十三、谈一下CAS
CAS体现的是一种乐观锁的思想,在不加锁的情况下保证操作数据的原子性,比如两个线程同事操作数据,线程a执行的是++,b执行--,a执行完毕之后,改变数值之前需要先进行比较,a执行完之后的数值,b拿去比较就会发现和之前不一样,这时候就进行自旋操作,把数值重新拿到在进行操作。
十四、乐观锁和悲观锁的区别
乐观锁是最乐观的思想,不怕别的线程修改共享变量,大不了自己吃点亏进行重试。
悲观锁是最悲观的思想,自己上了锁之后别的都不允许改变,释放了锁才会让别的线程操作。
十五、什么是AQS
AQS是多线程中的队列同步器,是一种锁机制,他是作为一个基础框架使用的。
AQS内部维护了一个先进先出的双向队列,队列中存储的排队的线程。
AQS内部有一个state,这个state相当于是一个资源,默认是0(无锁状态),如果队列中的有一个线程修改成功了,state改为1,则当前线程相当于获取了资源。
对state修改的时候使用cas操作,保证原子性。
十六、synchronized和Lock有什么区别
语法层面
synchronized是关键字,用c++实现。
Lock是接口,用java实现。
使用synchronized时,退出代码块锁会自动释放,Lock则需要手动调用unlock实现
功能层面。
二者都属于悲观锁,都具备基本的互斥、同步、重入功能。
Lock提供了很多功能,比如公平锁,可打断,可超时,多条件变量。
性能层面
没有竞争用synchronized,有竞争用Lock。
十七、ConcurrentHashMap
底层数据结构
1.7采用的是数组+链表
1.8采用的是数组+链表/红黑树
加锁的方式
1.7采用的是对Segment加锁,锁使用的是RenntrantLock
1.8采用CAS添加新节点,对链表或者红黑树首节点加锁,性能更好,锁粒度更细
十八、线程池的核心参数
1.核心线程数
2.最大线程数
3.生存时间
4.时间单位
5.阻塞队列
6.线程工厂
7.拒绝策略
十九、线程池执行原理
提交任务,检查核心线程数是否已满,没有满则添加到工作线程并且执行,满了则会去看阻塞队列是否已满,没有满则添加任务到阻塞队列,满了就会查看最大线程数是否满,未满则创建非核心线程执行任务,满了则采用拒绝策略。
二十、阻塞队列
1.ArrayBlockingQueue:基于数组结构的有界阻塞队列,先进先出。(强制有界)
2.LinkedBlockingQueue:基于链表结构的有界阻塞队列(单向链表)。(可以无界)(用的较多,头尾都会有锁)
3.DelayedWorkQueue:优先让执行时间短的任务先执行,优先级队列。
4.SynchronousQueqe:不存储元素的阻塞队列,每个插入前都必须等前一个移出。