Java并发八股

线程

什么是线程和进程?

** 什么是进程? **
进程是程序的一次执行过程,程序执行的基本单位。一个程序的运行就是一个进程从创建–运行–消亡的过程。
Java中启动mian函数时就是启动了一个JVM进程,main函数所在的线程就是主线程。
** 什么是线程? **
线程与进程类似,是比进程更小的执行单位。一个进程的执行过程中可以产生多个线程。与进程不同的是,同类的多个线程可以共享进程的** 堆 **和 ** 方法区 **资源。但每个线程有自己的本地方法栈,程序计数器,虚拟机栈。所以系统产生一个线程或者在线程中切换,开销较小。(Java天生就是一个多线程的程序)

Java线程与操作系统线程的区别?

Java线程本质就是操作系统线程(由操作系统内核进行管理和调度),采用一对一的线程模型(一个Java线程对应一个系统内核线程)

线程与进程的关系,区别,和优缺点?

关系:一个进程中可以有多个线程,多个线程共享进程的堆和方法区资源,每个线程有自己的程序计数器,虚拟机站,本地方法栈。线程是进程划分的更小的运行单位
区别:线程与进程最大的不同在于,进程之间基本上是独立的,线程则不一样,同一进程中的线程,可能会互相影响。
优缺点:线程执行开销小,但不利用资源的管理和保护,进程则相反。

程序计数器为什么是私有的?
程序计数器主要有两个作用:

  1. 字节码解释器通过改变程序计数器来读取指令,实现代码的流程控制(顺序执行,循环,异常处理)
  2. 在多线程的情况下,程序计数器用于记录当前线程执行的位置,从当线程被切换回来的时候那知道线程上次运行到哪。
    所以程序计数器私有主要是为了线程切换后能恢复到正确的执行位置。

虚拟机栈和本地方法栈为什么私有?

  1. 虚拟机栈:每个Java方法执行前会创建一个栈帧用于存储局部变量表、操作数栈、常量池引用等信息。从方法调用到执行完成,就对应着一个栈帧在Java虚拟机栈中入栈和出栈的过程。
  2. 本地方法栈:与Java虚拟机栈类似,区别虚拟机栈为的是Java方法的执行服务,本地方法栈为Native方法的执行服务。
    所以为了保证线程中的局部变量不被其他线程访问到,虚拟机栈和本地方法栈是线程私有的

简单了解堆和方法区
堆和方法区是所有线程共享的资源,堆是进程中最大的一块内存,主要用于存放新创建的对象(几乎所有对象都在这分配内存),方法区主要用于存放被加载的类信息、常量、静态变量等数据。

如何创建线程?

创建线程的方式有很多种,例如 继承 Thread 类、实现Runnable接口、实现Callable接口、使用线程池等等
严格来说,Java只有一种方式创建线程,通过new Thread().start()创建。上述方式最终都依赖于new Thread().start()

说说线程的生命周期和状态?

Java线程在运行的生命周期中处于以下6种状态中的一种:

  • NEW:初始状态,被创建出来,但没有被调用start()
  • RUNNABLE(running和ready状态切换,并发执行导致两种状态不停切换):运行状态,被调用了start()
  • BLOCKED:阻塞状态,等待锁被释放
  • WAITING:等待状态,表示该线程在等其他线程做出特定动作(通知)
  • TIME_WAITING:超时等待状态,可以在指定时间后自行返回
  • TERMINATED:终止状态,表示线程已经运行完毕

run()方法执行完毕后,就进入TERMINATED状态

操作系统层面有ready和running状态,JVM层面上只能看到runnable状态。
为什么JVM没有区分两种状态呢?
现在时分操作系统都是使用时间分片抢占式调度。时间分片通常很小,导致线程切换很快,区分两种状态就没什么意义。

什么是线程的上下文切换?
线程执行过程中有自己的运行状态和条件(程序计数器,栈信息等)。出现以下情况,线程会从占用CPU的状态中退出。

  • 主动让出CPU,调用了sleep()、wait()
  • 时间片用完,操作系统要防止一个线程或者进程长时间占用CPU,导致其他线程、进程锁死。
  • 调用了阻塞类型的系统中断,例如请求IO、线程被阻塞等。
  • 被终止或结束运行
    前3种都会继续上下文切换,上下文切换会占用CPU、内存等资源进行处理,如果频繁切换会造成系统效率低下。

Thread#sleep()方法和Object#wait()方法对比?

**共同点:**两者都可以暂停线程的执行
区别

  • sleep()方法没有释放锁,而wait()方法释放了锁
  • wait()常用于线程之间通信,sleep()通常用于暂停执行
  • wait()方法被调用,线程不会自动苏醒,需要别的线程调用同一个对象上的notify()或者notifyAll()方法。sleep()方法执行完,线程会自动苏醒。或者使用wait(long timeout),超时后线程自动苏醒。
  • sleep()Thread类的静态本地方法,wait()Object类的本地方法。

为什么wait()方法不定义在Thread中?
wait()是让获得对象锁的线程实现等待,会自动释放当前线程占用的对象锁。每一个对象都有对象锁,既然是释放当前线程占用的对象锁,自然是操作对应对象而非当前的线程。
sleep()方法同理。

可以直接调用Thread类的run方法吗?

new 一个Thread,线程进去新建状态。调用start()方法,会启动一个线程并且进去就绪状态,分配到时间片就开始运行。start()方法会执行线程相应的准备工作,然后自动执行run()方法,这是多线程工作的模式。如果直接执行run()方法,会把run()方法当一个main线程下的普通方法执行,而不是在某个线程中执行,不是多线程工作。
总结:调用start()方法,可以启动线程并且进入就绪状态,直接执行run()方法,不会以多线程方式执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值