1.线程与进程的区别是什么?
进程是所有线程的集合,每一个线程是线程中的一条执行路径.
2.为什么要使用多线程?
主要多线程可以提高程序运行效率.
3.多线程创建方式是?
a.继承Thread类,重写run方法
b.实现Runnable接口,重写run方法
c.使用匿名内部类
Thread thread = new Thread(new Runnable(){
public void run(){
//执行线程需要的逻辑
}
})
4.继承Thread类好还是实现Runnable接口好?
使用实现Runnable接口好,原因是实现了接口还是继续继承,而继承了一个类之后不能再继承了.
5.启动线程是start方法还是run方法?
开启线程是start方法,因为start方法会去创建线程,然后在调用run方法执行.
6.什么是用户线程,守护线程?
用户线程:平常创建的普通线程.
守护线程:为其他线程服务的线程,进程线程setDaemon(true)设置为守护线程,当主线程结束,
守护线程自动关闭.
7.五种多线程的运行状态是什么?
a.新建状态: 当用new操作符创建一个线程时,例如new Thread(obj),线程还没有开始运行,此时线程处于新建状态.当一个线程处于新生状态时,程序还没有开始运行线程中的代码.
b.就绪状态: 一个新创建的线程并不自动开始运行,要执行线程,就必须调用线程的start()方法.当线程对应调用start()方法即启动了线程,start()方法创建线程运行的系统资源,并调度线程运行的run()方法.当start()方法返回后.线程就处于就绪状态.
注意:处于就绪状态的线程并不一定立即运行run()方法,线程还必须同其他线程竞争CPU时间,只有获得CPU时间才可以运行线程.
c.运行状态:当获取CPU时间后,它才进入运行状态,真正开始执行run()方法.
d.阻塞状态:线程运行的过程中,可能由于各种原因进行阻塞状态:
1.线程通过调用sleep方法进入睡眠状态;
2.线程调用一个在I/O上被阻塞的操作,即该操作在输入输出操作完成之前不会返回到它的调用者;
3.线程试图得到一个锁,而该锁正被其他线程持有;
4.线程在等待某个触发条件;
f.死亡状态:即线程进行销毁,并且触动GC(垃圾回收)进行回收.
8.线程如何才能进行交替运行?
使用join()方法,当主线程中执行到T1.join()方法时,就认为主线程吧执行权让给了T1.
9.线程如何设置优先级?
使用setPriority(num) 方法.如t1.setPriority(1).
10.你知道如何暂停当前正在执行的线程,并执行其他线程么?什么方法?
Yield() 方法
11.什么是线程安全?
当多个线程对某一个类或者方法访问时,如果还存在正确的行为,那么称这个线程为线程安全的.
12.为什么会有线程安全问题?
因为当多个线程共享一个全局变量或静态变量时,做写的操作时,可能会发生数据冲突的问题,也就是线程安全的问题.
13.线程安全问题的解决办法知道吗?
使用synchronized或者使用Lock锁
14.为什么使用线程同步或者锁可以解决线程安全问题?
因为解决数据冲突的问题,只能让当前一个线程进行执行.代码执行完毕后释放锁,其他线程执行才能保证线程安全.
15.什么是多线程之间的同步?
当多个线程共享一个资源,不会受到其他线程的干扰
16.那同步的优点和缺点是什么?
优点:解决了线程安全问题.
缺点:多个线程在获取锁需要判断锁,并且使用synchronized有抢锁过程,比较消耗资源.
17.Java有那些内置锁呢?都有什么特性呢?
synchronized就是Java的内置锁, 具有原子性
18.什么是多线程的死锁?
同步中嵌套同步,导致锁无法释放
19.谈谈你对ThreadLocal的理解.
概念:ThreadLocal 是一个线程的局部变量,访问某个线程拥有自己的局部变量
ThreadLocal类的接口:
a.void set(Object value):设置当前线程的线程局部变量的值
b.public Object get():返回当前线程局部变量
c.public void remove(): 将当前线程局部变量的值删除,目的减少内存的占用
d.protected Object initialValue(): 返回该线程局部变量的初始值
20.ThreadLocal内部数据结构了解吗?
每一个Thread内部都有一个ThreadLocalMap,ThreadLocalMap里面存储线程本地对象(Key)和线程变量副本(value).
21.ThreadLocalMap是如何解决冲突问题的?具体能说说吗?为什么会它会造成内存泄漏?
解决hash冲突的方式就是步长加一或者减一,寻找下一相邻的位置(结构简单,没有next引用,采取线性侦探方式,根据hashcode确定元素位置,如果发现位置上已经有其他key值,则使用固定算法寻找下一个位置)
ThreadLocalMap使用Entry来保存K-V结构数据,但是Entry继承自WeakReference(弱引用:生命只能活到下次GC前),但数据结构只有key是弱引用,而value还是强引用的.所以发生GC的时候,key被回收了,但是value还没有回收,这就会造成内存泄漏问题.最好的做法是使用完成调用remove方法进行清空回收内存.
22.多线程的三大特性是什么?
a.原子性:即一个操作或者多个操作,要么全部执行并且执行过程不会被任何因素打扰,要么就都不执行.
b.可见性:当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程也能够立即看到修改的值.
c.有序性:程序按照代码的先后顺序执行.
23.什么是Java内存模型?
Java内存模型简称JMM,定义了一个线程对另一个线程可见,共享变量在主内存中, 每个线程都有自己的本地内存,当多个线程同时访问一个数据的时候,可能本地内存没有及时刷新到主内存,就会发生线程安全问题.
24.Java中如何保证线程之间的可见性?
使用volatile关键字
25.什么是volatile?你可以简单说说吗?
某些被volatile修饰的变量,在线程修改的时候,它会保证修改的值会立即刷新到主内存中,当有其他线程需要读取时,可以立即获取修改后的值
26.volatile可以保证原子性吗?有什么特性呢?
volatile保证了线程间共享变量的及时可见性,但不能保证原子性.
特性:
a.保证此变量对所有线程的可见性
b.禁止指令重排序(内存屏障):是指CPU允许将多条执行不按照程序规定顺序执行两个没有依赖关系的上下文程序.
27.什么是重排序?
为了充分运行cpu的快速运算能力,首先编译器在编译的时候,先进行一次重排序,执行的时候还会进行一次重排序
28.as-if-serial语义了解吗?
不管怎么重排序,程序的执行结果不能别改变.
29.重排序对多线程有影响吗?
在单线程程序中,对存在控制依赖关系操作的重排序不会改变执行结果,但是在多线程程序中,对存在控制依赖的操作重排序,可能会改变程序的运行结果(原因在存在流程控制关系的代码,CPU会采取试探的方式进行,先执行在写入重排序缓存区,可能其他线程还没有执行程序就获取到结果了,导致结果不准确)
30.内存屏障都有哪些呢?
a. LoadLoad屏障:对于这样的语句读取代码1; LoadLoad(屏障);读取代码2,在读取代码2后续的读取操作前,保证读取代码1的数据要先被读取完.
b.StoreStore屏障:对于这样的语句存储代码1;StoreStore;存储代码2 , 在存储代码2以及后续写入操作执行前,保证存储代码1写入操作对其他处理器可见
c.LoadStore屏障:对于这样的语句读取代码1;LoadStore;存储代码2.在存储代码2写入操作之前,要保证读取代码1要先被读取完毕.
d.StoreLoad屏障:对于这样的语句存储代码1;StoreLoad;读取代码2,在读取代码2的操作前,需要保证存储代码1的写入对所有处理器可见.