面试题---并发

1.程序计数器为什么是私有的?
为了线程切换后能恢复到正确的执行位置。

2.虚拟机栈和本地方法栈为什么是私有的?
虚拟机栈: 每个 Java 方法在执行的同时会创建一个栈帧用于存储局部变量表、操作数栈、常量池引用等信息。从方法调用直至执行完成的过程,就对应着一个栈帧在 Java 虚拟机栈中入栈和出栈的过程。

本地方法栈: 和虚拟机栈所发挥的作用非常相似,区别是: 虚拟机栈为虚拟机执行 Java 方法 (也就是字节码)服务,而本地方法栈则为虚拟机使用到的 Native 方法服务。 在 HotSpot 虚拟机中和 Java 虚拟机栈合二为一。

为了保证线程中局部变量不被别的线程访问到,虚拟机栈和本地方法栈是线程私有的。

3.堆和方法区?

堆和方法区是所有线程共享的资源,其中堆是进程中最大的一块内存,主要用于存放新创建的对象(几乎所有对象都在这里分配内存),方法区主要用于存放已被加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

4.并发与并行?
并发:同一时间段,多个任务都在执行(单位时间内不一定同时执行)
并行:单位时间内,多个任务同时执行

5.为什么要使用多线程?
总体上–
-从计算机底层来说: 线程可以比作是轻量级的进程,是程序执行的最小单位,线程间的切换和调度的成本远远小于进程。另外,多核 CPU 时代意味着多个线程可以同时运行,这减少了线程上下文切换的开销。
-从当代互联网发展趋势来说:现在的系统动不动就要求百万级甚至千万级的并发量,而多线程并发编程正是开发高并发系统的基础,利用好多线程机制可以大大提高系统整体的并发能力以及性能。

计算机底层来探讨–
-单核时代:单核时代多线程主要是为了提高CPU和IO设备的综合利用率。
-多核时代:多核时代多线程主要是为了提高CPU利用率。

6.多线程带来的问题?
并发编程的目的是为了提高程序的执行效率提高程序运行速度,但是并发编程并不总是能提高程序运行速度的。还会遇到很多问题,比如:内存泄漏、死锁、线程不安全等。

7.线程的生命周期?
在这里插入图片描述
线程创建之后它将处于 NEW(新建) 状态,调用 start() 方法后开始运行,线程这时候处于 READY(可运行) 状态。可运行状态的线程获得了 CPU 时间片(timeslice)后就处于 RUNNING(运行) 状态。

当线程执行 wait()方法之后,线程进入 WAITING(等待) 状态。进入等待状态的线程需要依靠其他线程的通知才能够返回到运行状态,而 TIME_WAITING(超时等待) 状态相当于在等待状态的基础上增加了超时限制,比如通过 sleep(long millis)方法或 wait(long millis)方法可以将 Java 线程置于 TIMED WAITING 状态。当超时时间到达后 Java 线程将会返回到 RUNNABLE 状态。当线程调用同步方法时,在没有获取到锁的情况下,线程将会进入到 BLOCKED(阻塞) 状态。线程在执行 Runnable 的run()方法之后将会进入到 TERMINATED(终止) 状态。

8.什么是上下文切换?
任务从保存到再加载的过程就是一次上下文切换。

9.产生死锁的四个必备条件?
(1)互斥条件:该资源任意一个时刻只由一个线程占用。
(2)请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3)不剥夺条件:线程已获得的资源在未使用完之前不能被其他线程强行剥夺,只有自己使用完毕后才能释放资源。
(4)循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

10.如何预防和避免线程死锁?
(1)破坏请求与保持条件 :一次性申请所有的资源。
(2)破坏不剥夺条件 :占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源。
(3)破坏循环等待条件 :靠按序申请资源来预防。按某一顺序申请资源,释放资源则反序释放。破坏循环等待条件。

11.sleep()方法和wait()方法区别和共同点?
-主要的区别在于:sleep()方法没有释放锁,而wait方法释放了锁。
-两者都可以暂停线程的执行。
-wait()通常被用于线程间交互/通信,sleep()通常被用于暂停执行。
-wait()方法被调用后,线程不会自动苏醒,需要别的线程调用同一个对象上的 -notify() 或者 notifyAll() 方法。sleep() 方法执行完成后,线程会自动苏醒。或者可以使用 wait(long timeout) 超时后线程会自动苏醒。

12.为什么调用start()方法会执行run()方法,为什么我们不能直接调用run()方法?
new一个Thread,线程进入了新建状态。调用start()方法,会启动一个线程并使线程进入了就绪状态,当分配到时间片后就可以开始运行了。start()会执行线程的相应准备工作,然后自动执行run()方法的内容,这是真正的多线程工作。但是直接执行run()方法,会把run()方法当成一个main线程下的普通方法去执行,并不会在某个线程中执行它,所以这不是多线程工作。

总结:调用start()方法方可启动线程并使线程进入就绪状态,直接执行run()方法的话不会以多线程方式执行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值