面试-并发编程

36 阅读4分钟

1. 并行,并发和串行有什么区别?

  • 并行在时间上是重叠的,两个及两个以上的任务在同一时刻互不干扰的同时执行
  • 并发允许两个线程彼此干扰,同一时刻,只有一个任务执行,但是一个时间段内,两个线程都交替执行完成
  • 串行在时间上不可能重叠,前一个任务还没有执行完成,下一个任务就只能等着

2. 什么是进程和线程?

  • 进程是程序的一次执行过程, 是系统进行资源分配和调度的基本单位,因此进程是动态的据。系统运行一个程序既是一个进程从创建,运行到消亡的过程。

在Java中,当我们启动一个main函数时其实就是启动了一个JVM的进程,而main函数所在的线程就是这个进程中的一个线程,也称主线程。

  • 线程与进程相似,但线程是一个比进程更小的执行单位,一个进程在执行过程中可以产生多个线程,与进程不同的是同类的多个线程共享进程的堆和方法区(JDK1.8之后的元空间)的资源,但每个线程有自己的程序计数器,虚拟机栈和本地方法栈,所以在产生一个线程,或是在各个线程之间切换工作时,负担要比进程小的多,因此线程也被称为轻量级进程。

:线程是进程划分成的更小的运行单位。线程和进程的最大不同在于基本上各进程是独立的,而各线程不一定,因为同一进程中的线程极有可能会相互影响。线程执行开销小,但不利于资源的管理和保护;而进程正相反。

3. 线程有哪几种创建方式?

  • 继承Thread类,重写run()方法,调用start()方法启动线程
  • 实现Runnable接口,重写run()方法
  • 实现Callable接口,重写call()方法,这种方式可以通过FutureTask获取任务执行的返回值
  • 通过线程池创建线程,定一个 Runnable 的实现类,重写 run 方法,然后创建一个拥有固定线程数的线程池, 最后通过 ExecutorService 对象的 execute 方法传入线程对象。

:其实本质上,创建线程只有一只方式,就是构造Thread类,最终都会创建Thread类(或其子类)的对象,可以看这篇文章:创建线程有几种方式?

4. 为什么调用start()方法时会执行run()方法,那怎么不直接调用run()方法?

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

5. 同步和异步的区别?

  • 同步: 发出一个调用之后,在没有得到结果之前,该调用就不可以返回,一直等待。
  • 异步: 调用在发出之后,不用等待返回结果,该调用直接返回。

6. 为什么要使用多线程?

选择多线程的原因,就是快

举个例子:如果要把1000块砖搬到顶楼,假设顶楼有几个电梯,是用一个电梯搬运块,还是同时用好几个同时搬运快呢? 这个电梯就可以理解为线程

所以,使用多线程就是因为: 在正确的场景下,设置恰当数目的线程,可以用来提高程序的运行速率.就是充分的利用CPU和I/O的利用率,提成程序运行速率。

当然,有利就有弊,多线程场景下,我们要保证线程安全,就需要考虑加锁。加锁如果不恰当,就很很耗性能。

参考:

Java 全栈知识体系

面试指南

多线程50问