线程相关面试题
线程
多线程会带来什么问题
使用多线程会出现内存泄露,上下文切换,死锁问题等
线程的生命周期
线程被创建,进入初始化状态
线程调用start方法进入就绪状态等待获取cpu时间片
当线程获取到时间片后,进入运行状态
在运行状态调用wait方法,线程就会进入等待状态,需要其他线程调用notify方法或notifyAll方法就会重新进入就绪状态
在运行状态调用sleep方法时,线程进入超时等待状态,等到时间到达后该线程就会进入就绪状态
在线程在运行状态需要调用synchronize同步锁时,而其他线程真用同步锁,该线程就会进入同步阻塞状态
当运行状态的线程调用yield让步方法时,该线程会由运行状态进入就绪状态
当线程执行完任务后就会进入终止状态
什么是上下文切换
当线程在执行任务没有完成但是cpu时间片到了切换下一个任务是,该线程会保存当前线程的任务完成度,然后进入就绪状态,当该线程再次进入运行状态时会在之前记录的任务进度上继续执行任务
什么线程死锁
两个或两个以上的线程相互持有对方所需要的资源,因为线程要执行完任务后才会释放资源,所以线程在循环等待对方所持有的资源,造成线程死锁
造成死锁的四个条件
互斥条件:资源在任意时刻只能被一个线程占用
请求和保持条件:线程在请求资源时阻塞,已持有的资源不会释放
不剥夺条件:线程不会强行抢夺其他线程的资源
循环等待条件:两个或两个以上的线程持有对方所需的资源
避免线程的方式
互斥条件无法破坏,因为枷锁就是为了让他们互斥的
破坏请求和保持条件:一次性请求资源
破坏剥夺条件:占用部分资源的线程进一步申请,如果没有申请成功就主动释放资源
破坏循环等待条件:按某一顺序进行申请资源
并行和并发的区别
并发:在某一时段内,多个线程在执行
并行:在单位时间内,多个任务同时执行
sleep和wait方法的区别
sleep和wait方法都会让线程进入阻塞状态
1.sleep是属于Thread类,wait是属于Object
2.sleep不会释放锁,wait会释放锁
3.sleep会自动苏醒,到时间后会从就绪状态转到运行状态
wait不会自动苏醒,需要其他线程通知,即其他线程调用notify方法或则notifyAll方法
synchronize关键字的作用
确保synchronize修饰的方法或则代码块能够任意时刻只执行一个线程
怎么使用synchronize关键字的
修饰实例方法:给当前对象加锁,在进入同步方法前要获取对象实例的锁
修饰静态方法:给当前的类加锁,在进入同步方法前获取当前类的锁
修饰代码块:给给定对象加锁,在进入同步方法前获取给定对象的锁
两个线程分别调用实例方法和静态方法不会发生互斥,因为访问静态方法占用的是类的锁,访问非静态方法的是对象实例的锁
什么是双重检查锁实现单例?怎么实现的
创建单列对象是进行两次判断实例是否存在,第一次加锁检查第二次不加锁检查
定义一个volatile修饰的变量接收创建的实例,使用volatile是为了禁止jvm的指令重排,定义无参构造器,然后判断当前的实例是否为空,目的是防止已创建的实例的对象进入,然后进行线程加锁,在判断实例是否为空,为空进行创建实例
创建实例不是原子性的,分为三步,1.分配内存空间,2.初始化实例,3.将实例指向分配的内存地址,因为jvm指令重排的原因,可以能创建实例的顺序为132