java 线程面试

153 阅读4分钟

记录下,面试的时候遇到的线程面试题。

  1. 线程有几种状态?
  • 初始(NEW):新创建了一个线程对象,但还没有调用start()方法。
  • 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。
  • 阻塞(BLOCKED):表示线程阻塞于锁。
  • 等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
  • 超时等待(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回。
  • 终止(TERMINATED):表示该线程已经执行完毕。
  1. 设计线程中断的意义是什么?

    当线程处于等待中,又不希望停止线程,使得业务数据丢失,采用线程中断给线程发出中断标识,使得线程跳出等待,执行线程中断后的逻辑。

  2. Java 中 interrupted 和 isInterrupted 方法的区别?

    • interrupted 清除中断状态
    • isInterrupted 不清除中断状态。
  3. 有三个线程 T1,T2,T3,怎么确保它们按顺序执行?

    主线程中使用join()来实现对线程的阻塞

    T1.start();
    T1.join();
    T2.start();
    T2.join();
    T3.start();
    T3.join();
    
  4. 为什么 wait 和 notify 方法要在同步块中调用

    wait 和 notify是成对出现的,用于线程之间的通信,他们存在竞态,我们必须保证在满足条件的情况下才进行wait。换句话说,如果不加锁的话,那么wait被调用的时候可能wait的条件已经不满足了(如上述)。由于错误的条件下进行了wait,那么就有可能永远不会被notify到,所以我们需要强制wait/notify在synchronized中。

  5. 线程池是什么,提交一个任务进去,处理流程?

    线程池用来管理线程,避免创建大量的线程增加开销。

    流程:

    1.判断当前池中线程是否比核心数少,否则新建一个线程执行任务

    2.核心池已满,但任务队列未满,添加到队列中

    3.核心池已满,队列已满,试着创建一个新线程

    4.按照处理策略,执行任务。

  6. Executor 框架介绍

    Executor 框架包括:线程池,Executor,Executors,ExecutorService,CompletionService,Future,Callable 等。 Executor 接口中之定义了一个方法 execute(Runnable command),该方法接收一个 Runable 实例,它用来执行一个任务,任务即一个实现了 Runnable 接口的类。

    ExecutorService 接口继承自 Executor 接口,它提供了更丰富的实现多线程的方法,比如,ExecutorService 提供了关闭自己的方法,以及可为跟踪一个或多个异步任务执行状况而生成 Future 的方法。 可以调用 ExecutorService 的 shutdown()方法来平滑地关闭 ExecutorService,调用该方法后,将导致 ExecutorService 停止接受任何新的任务且等待已经提交的任务执行完成(已经提交的任务会分两类:一类是已经在执行的,另一类是还没有开始执行的),当所有已经提交的任务执行完毕后将会关闭 ExecutorService。因此我们一般用该接口来实现和管理多线程。

    ExecutorService 的生命周期包括三种状态:运行、关闭、终止。创建后便进入运行状态,当调用了 shutdown()方法时,便进入关闭状态,此时意味着 ExecutorService 不再接受新的任务,但它还在执行已经提交了的任务,当素有已经提交了的任务执行完后,便到达终止状态。如果不调用 shutdown()方法,ExecutorService 会一直处在运行状态,不断接收新的任务,执行新的任务,服务器端一般不需要关闭它,保持一直运行即可。

    Executors 提供了一系列工厂方法用于创先线程池,返回的线程池都实现了 ExecutorService 接口。