自学内容网 自学内容网

Java面试篇【并发编程】常见面试题(2024最新)

Java并发编程常见面试题

1.什么是线程和进程?

进程是操作系统分配资源的最小单位,各个进程之间占据独立的寻址空间,运行也是独立运行,进程间通信需要一些机制。进程间切换需要的开销较大。
线程是程序执行的基本单位,一个进程可以开启多个线程,他们的很多空间,比如堆空间,其他资源都是公用的。对于java来说,线程有自己的虚拟机栈,本地方法栈,和程序计数器。线程执行开销小,但是不够安全。

2. 虚拟机栈和本地方法栈,程序计数器为什么是私有的?

- 虚拟机栈:每个java方法在执行的时候,都会创建栈帧,来记录局部变量,操作数栈,引用等等。为了保证线程的局部变量不被别的线程访问,应该设为私有。
- 本地方法栈道理类似。程序计数器是记录方法执行到了哪里,用来在线程切换的时候恢复到正确的位置,自然要一个线程一个。

3.线程的生命周期与状态

在这里插入图片描述
在这里插入图片描述
线程创建之后处于New阶段,调用start()方法之后,处于ready阶段,获得cpu时间片时处于running阶段。
但是操作系统笼统认为处于runnable阶段。
执行wait()、join()之后,进入WAITING阶段,等待别的线程的通知,才能正常运行,此时释放资源。
执行sleep(long millis),wait(long millis)之后,进入TIME_WAITING阶段。时间过了就回到Runnable阶段。
在调用同步方法,却没有获得锁的时候,进入block阶段,执行完run方法,进入TERMINATED阶段。

4. 什么是线程死锁

持有对方想要的资源,期待获得对方持有的资源,形成了一个圈。互相等待谁也不让。
在这里插入图片描述

public class DeadLockDemo{
    private static Object obj1 = new Object();
    private static Object obj2 = new Object();
    public static void main(String[] args){
        new Thread(()->{
            synchronized(obj1){
                System.out.println(Thread.currentThread()+"get obj1");
                try{
                    Thread.sleep(1000);
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread()+"waiting obj2");
                synchronized(obj2){
                    System.out.println(Thread.currentThread()+"get obj2");
                }
            }
        },"thread-1").start();
        new Thread(()->{
            synchronized(obj2){
                System.out.println(Thread.currentThread()+"get obj2");
                try{
                    Thread.sleep(1000);
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread()+"waiting obj1");
                synchronized(obj1){
                    System.out.println(Thread.currentThread()+"get obj1");
                }
            }
        },"thread-2").start();
    }
}

5.如何避免线程死锁?

死锁产生的四个条件:
1.互斥。该资源任意时刻只能由一个线程占用。
2.请求与保持:一个进程因为因请求资源而阻塞时,自己占有的资源不会释放。
3.不剥夺条件:线程自己获得的只能自己使用完毕自己释放,不能被强行剥夺。
4.循环等待:互相持有和等待资源需要形成一个头尾相接的闭环。

避免死锁:
1.破坏请求与保持条件:占用部分资源的线程进一步申请其他资源的时候,如果申请不到,可以主动释放资源。
2.破坏不剥夺条件:一次性请求所有资源。
3.破坏循环等待条件:按照顺序请求资源,避免循环等待情况。

6.sleep()和wait()的区别和共同点?

1.sleep()方法没有释放锁,wait()会释放锁。
2.sleep()通常用来暂停线程。到了时间会自动苏醒。wait()通常用来线程间交互/通信,不会自动苏醒,需要其他线程调用notify()或者notifyAll()。

7.调用start方法会执行run()方法,为什么不能直接调用run()方法?

start()会执行线程的准备工作,然后得到时间片后就可以执行run()方法的内容了。但是run()方法本质上是一个普通方法。如果直接执行,那就没有新建线程,就是在原来的线程执行的。只有执行了start()方法,才能启动多线程。


原文地址:https://blog.csdn.net/zhangzhanbin/article/details/136507600

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!