多线程面试题【基本概念和线程创建】_Java

你怎么理解线程?

  • 说到线程,一般要说到进程。
  • 进程是指每个独立程序在计算机上的一次执行活动,例如运行中的微信程序等。
  • 进程进一步可以细化为线程,线程是一个程序内部的一条执行路径。如果一个程序中可以在同一时间内执行多个线程,就说这个程序是支持多线程的。

线程和进程有什么区别?

  • 从定义来说,线程只是一个程序内部的一条执行路径,而进程是所有线程的集合。
  • 从切换开销来说,线程间的切换开销小,而进程间的切换开销大。

Java中线程分为哪几类?

  • Java中的线程分为两类:一种是用户线程,另一种是守护线程。任何线程都可以是“用户线程”或“守护线程”,它们几乎在每个方面都是一样的,唯一的区别是判断虚拟机何时离开。
  • 用户线程:Java虚拟机在它所有非守护线程都已经离开后自动离开。
  • 守护线程:是用来服务用户线程的,如果没有其他用户线程在运行,那么就没有可服务的对象,也就没有理由继续下去。也被称为“后台线程”或“精灵线程”。
  • Java垃圾回收线程就是一个典型的守护线程,当程序中不再有任何运行中的线程时,程序就不会再产生垃圾,垃圾回收器也就无事可做,所以当垃圾回收线程是Java虚拟机上仅剩的线程时,Java虚拟机会自动离开,结束程序的运行。

一个用户线程如何变成一个守护线程?

  • 使用setDaemon(true)方法设置。

并发和并行分别指什么?

  • 并发和并行是两个概念。
  • 并行指同一时刻有多条指令在多个处理器上同时执行。
  • 并发指同一时刻只能有一条指令执行,但多个进程指令被快速轮换执行,使得在宏观上具有多个进程同时执行的效果。

在什么情况下需要用到过多线程?

  • 程序需要同时执行两个或多个任务时;
  • 程序需要实现一些需要等待的任务时,例如用户输入等;
  • 需要一些后台运行的程序时。

多线程有什么优点?

  • 提高应用程序响应,增强用户体验。
  • 提高计算机CPU的利用率,节省响应时间。
  • 改善程序结构。

多线程有几大特性?分别是什么?

  • 多线程有3大特性,分别为原子性、可见性、有序性。
  • 原子性是指一个操作是不可中断的。
  • 可见性是指当一个线程修改了某一个共享变量的值,其他线程是否能够立即知道这个修改。
  • 有序性是指在并发时,程序的执行可能会出现乱序。给人的直观感觉就是:写在前面的代码,会在后面执行。

创建线程有哪几种方式?

推荐阅读:创建线程主要有3种方式:

  • 通过继承Thread类来创建
  • 通过实现Runnable接口来创建
  • 通过实现Callable接口来创建

如何通过继承Thread类来创建并启动多线程?

  • 定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务。
  • 创建Thread子类的实例,即创建了线程对象。
  • 调用线程对象的start()方法来启动该线程。

如何通过实现Runnable接口来创建并启动多线程?

  • 定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体是该线程的线程执行体。
  • 创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
  • 调用线程对象的start()方法来启动该线程。

如何通过实现Callable接口来实现线程类?

  • 创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,且该call()方法有返回值,再创建Callable实现类的实例。
  • 使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法 的返回值。
  • 使用FutureTask对象作为Thread对象的target创建并启动新线程。
  • 调用FutureTask类对象的get()方法来获得子线程执行结束后的返回值。

你认为用哪种方法实现多线程最好?为什么?

  • 一般推荐采用实现Runnable接口、Callcable接口的方式来创建多线程,因为相较于继承Thread类的方法,实现Runnable接口、Callcable接口的方式有如下优点:
  • 线程类只是实现了Runnable接口或者Callcable接口,还可以继承其他类。
  • 在这种方式下,多个线程可以共享同一个target对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU、代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。

线程的run()方法和start()方法有什么区别和联系?

  • 启动线程使用start()方法,而不是run()方法;
  • 调用start()方法来启动线程,系统会把该run()方法当成线程执行体来处理;
  • 如果直接调用线程对象的run()方法,则run()方法立即就会被执行,而且在run()方法返回之前其他线程无法并行执行。