021. 线程的生命周期
新建状态(new一个线程的时候)
调用线程.start方法的时候,等待cpu分配时间片
可运行状态
当cpu分配到了时间片之后,线程开始运行,运行run方法当中的内容
运行状态
当线程遇到sleep、wait等方法的时候,线程会进入阻塞状态
阻塞状态
当休眠时间到期,或者被notify了,线程又回到了可运行状态
死亡状态
线程运行结束之后,就会销毁,被jvm的gc回收
022. 线程常用方法
1.start() : 线程调用该方法将启动线程,使之从新建状态进入就绪队列排队,一旦轮到它来享用 CPU 资源时,就可以脱离创建它的线程独立开始自己的生命周期了。
2.run(): Thread 类的 run()方法与 Runnable 接口中的 run()方法的功能和作用相同,都用来定义线程对象被调度之后所执行的操作,都是系统自动调用而用户程序不得引用的方法。
3.sleep(int millsecond): 优先级高的线程可以在它的 run()方法中调用 sleep 方法来使自己放弃 CPU 资源,休眠一段时间。
4.isAlive(): 线程处于“新建”状态时,线程调用 isAlive()方法返回 false。在线程的 run()方法结束之前,即没有进入死亡状态之前,线程调用 isAlive()方法返回 true.
5.currentThread():该方法是 Thread 类中的类方法,可以用类名调用,该方法返回当前正在使用 CPU 资源的线程。
6.interrupt() :一个占有 CPU 资源的线程可以让休眠的线程调用 interrupt()方法“吵醒”自己,即导致休眠的线程发生 InterruptedException 异常,从而结束休眠,重新排队等待 CPU 资源。
7.join() :线程加入,主线程需要在子线程执行之后再结束。这就需要用到 join()方法,通过 join 方法,对线程执行
顺序进行排序;
8.yield(): 线程礼让,线程依次运行,理论上平均分配 CPU 时间片,不会抢夺;
023. sleep() 和 wait() 有什么区别
类的不同:sleep() 来自 Thread,wait() 来自 Object。
释放锁:sleep() 不释放锁;wait() 释放锁。
用法不同:sleep() 时间到会自动恢复;wait() 可以使用 notify()/notifyAll()直接唤醒。
024. notify()和 notifyAll()有什么区别
notifyAll()会唤醒所有的线程,notify()之后唤醒一个线程。notifyAll() 调用后,会将全部线程由等待池移到锁池,然后参与锁的竞争,竞争成功则继续执行,如果不成功则留在锁池等待锁被释放后再次参与竞争。而 notify()
只会唤醒一个线程,具体唤醒哪一个线程由虚拟机控制。
025. 线程的 run() 和 start() 有什么区别
start() 方法用于启动线程,run() 方法用于执行线程的运行时代码。
run() 可以重复调用,而 start() 只能调用一次。
026. synchronized 和 Lock 的区别
1、synchronized 可以给类、方法、代码块加锁;而 lock 只能给代码块加锁。
2、synchronized 不需要手动获取锁和释放锁,使用简单,发生异常会自动释放锁,不会造成死锁;而 lock 需要自己加锁和释放锁,如果使用不当没有 unLock()去释放锁就会造成死锁。
3、通过 Lock 可以知道有没有成功获取锁,而 synchronized 却无法办到。
027线程之间如何进行通信?
1:使用synchronized锁的wait和notify进行等待和唤醒
2:使用lock锁的condition的await和signal进行等待唤醒
029. 什么导致线程阻塞
阻塞状态的线程的特点是:该线程放弃 CPU 的使用,暂停运行,只有等到导致阻塞的原因消除之后才恢复运行。或者是被其他的线程中断,该线程也会退出阻塞状态.
1)线程执行了 Thread.sleep(intmillsecond);方法,当前线程放弃 CPU,睡眠一段时间,然后再恢复执行
2)线程执行一段同步代码,但是尚且无法获得相关的同步锁,只能进入阻塞状态,等到获取了同步锁,才能回复执行。
3)线程执行了一个对象的 wait()方法,直接进入阻塞状态,等待其他线程执行 notify()或者 notifyAll()方法。
4)线程执行某些 IO 操作,因为等待相关的资源而进入了阻塞状态。
030. 什么是死锁如何防止死锁
当线程 A 持有独占锁 a,并尝试去获取独占锁 b 的同时,线程 B 持有独占锁 b,并尝试获取独占锁 a 的情况下,就会发生 AB 两个线程由于互相持有对方需要的锁,而发生的阻塞现象,我们称为死锁。简单来说,就是两个线程为了争抢资源而发生的相互等待的线程阻塞现象。
1、尽量使用 tryLock的方法,设置超时时间,超时可以退出防止死锁。
2、尽量使用 Java.util.concurrent 并发类代替自己手写锁。
3、尽量降低锁的使用粒度,尽量不要几个功能用同一把锁。
4、尽量减少同步的代码块。
更多面试题,在主页,java面试题分栏中