笔试题总结——笔试中常见的多线程方法相关问题
通过最近做笔试题发现多次问到多线程方法的相关问题,本篇文章将对这些方法进行解答分析。
几种常用方法的用途?
多线程中有哪些方法会释放锁?
多线程中有哪些方法会释放CPU资源?
join和sleep的区别?
首先看几种常用方法的用途,这个没什么可说的,都是一些概念需要记忆的东西,这里简单列举一下,具体的可以参考:多线程常用方法的使用。
sleep():让当前线程暂缓执行,直到预计时间后再恢复执行。
yield():暂停执行当前线程,并执行其他线程
join():等待其他线程终止再执行当前线程
interrupt():设置线程的中断状态,用于线程停止
多线程中哪些方法会释放锁?
join():对wait()的包装
wait():虽然不仅限于多线程中,但也是会释放锁的
await():存在于Condition机制中,也会释放锁
多线程中哪些方法会释放CPU资源?
sleep():立即交出CPU资源
yield():会交出CPU,但不一定立即交出
代码块中存在什么会导致线程中断状态interrupt()出现异常?
概述:当线程在活动之前或活动期间处于正在等待、休眠或占用状态且该线程被中断时,抛出该异常
体现在多线程上就是:
java.lang.Object 类的 wait 方法
java.lang.Thread 类的 sleep 方法
java.lang.Thread 类的 join 方法(内部用的还是wait())
join和sleep的区别?
最主要的区别就在于锁的释放问题上:
join(long):内部是由wait(long)实现的,因此具有释放锁的特点,其他线程就可以调用此线程中的同步方法了。
sleep(long):并不会释放锁。
举一个简单的例子,验证sleep()方法不会释放锁,而join()方法会释放锁。
1、sleep()情况下
ThreadA中开启了ThreadB类的对象b,给b对象加锁,此时A持有对象b的锁,然后将b启动后,ThreadA睡上6s,而主线程中只睡了1s,也就是1s后,ThreadC也被启动了,看是否释放锁就看ThreadC被启动后,ThreadC调用对象b的同步方法和ThreadA调用b对象的后续语句的执行顺序,
sleep()不释放锁:ThreadA在睡6s的过程中始终持有着对象b的锁,因此ThreadC只能等待ThreadA结束后才能调用对象b的同步方法。
2、join()情况下
join()释放锁:ThreadA中调用b.join(),在等待b.run()执行过程中,释放了锁,此时ThreadC开启后,获取到对象b的锁,直接执行了b的同步方法。
class ThreadA extends Thread{
private ThreadB b;
public ThreadA(ThreadB b) {
super();
this.b = b;
}
@Override
public void run() {
try {
synchronized (b){
b.start();
// Thread.sleep()不释放锁
// Thread.sleep(6000);
// Thread.join()释放了b的锁
b.join();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class ThreadB extends Thread{
@Override
public void run() {
try {
System.out.println(" b run begin timer="+System.currentTimeMillis());
Thread.sleep(5000);
System.out.println(" b run end timer="+System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void bService(){
System.out.println("打印了bService timer="+System.currentTimeMillis());
}
}
class ThreadC extends Thread{
private ThreadB threadB;
public ThreadC(ThreadB threadB) {
super();
this.threadB = threadB;
}
@Override
public void run() {
threadB.bService();
}
}
public class SleepAndJoinTest {
public static void main(String[] args) {
try {
ThreadB b = new ThreadB();
ThreadA a = new ThreadA(b);
a.start();
Thread.sleep(1000);
ThreadC c = new ThreadC(b);
c.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
根据打印的结果可以验证sleep()不释放锁,而join()会释放锁。
Thread.sleep()输出结果如下:
b run begin timer=1563328516857
b run end timer=1563328521857
打印了bService timer=1563328522857
b.join()输出结果如下:
b run begin timer=1563328419238
打印了bService timer=1563328420238
b run end timer=1563328424243