Java多线程面试题

1.进程和线程的区别

程序由指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至 CPU中,数据加载至内存。在指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理 IO 的。
当一个程序被运行,从磁盘加载这个程序的代码到内存中,这时就开启了一个进程。

什么叫做进程:当一个程序被允许,从磁盘加载到这个程序的代码至内存,这时就开启了一个进程。(比如:打开QQ软件,QQ运行后就是一个进程)
什么叫做线程:线程就是一个指令流,将指令流中的一条条指令以一定顺序交给CPU执行。
进程和线程的区别:

  • 进程是正在运行程序的实例,进程中包含了多个线程,每个线程执行不同的任务。
  • 不同的进程使用不同的内存空间(QQ进程与微信进程使用的内存空间是不同的),当前进程下的所有线程可以共享内存空间。
  • 线程比进程更轻量,线程上下文切换成本一般比进程低(上下文切换指的是一个线程切换到另一个线程)

2.并行和并发的区别

两种情况:单核CPU和多核CPU

1.单核CPU

  • 单核CPU下线程实际还是串行执行的
  • 操作系统中有一个组件叫做任务调度器,将cpu的时间片(windows下时间片最小约为 15 毫秒)分给不同的程序使用,只是由于cpu在线程间(时间片很短)切换的速度非常快,给人的感觉是同时运行的 。
  • 总结为一句话就是: 微观串行,宏观并行
  • 一般会将这种线程轮流使用CPU的做法称为并发(concurrent)

2.多核CPU

每个核(core)都可以调度运行线程,这时候线程可以是并行的。

3.并行和并发有什么区别?

并发(concurrent)是同一时间应对(dealing with)多件事情的能力,(在同一刻时间上,还是只做一件事)

并行(parallel)是同一时间动手做 (doing)多件事情的能力,(同一刻时间内,多核CPU同时做多件事)

4.总结

现在都是多核CPU,在多核CPU下
并发是同一时间应对多件事情的能力,多个线程轮流使用一个或多个CPU
并行是同一时间动手做多件事情的能力,4核CPU同时执行4个线程

3.创建线程的方式有哪些?

  • 继承Thread类
  • 实现Runnable接口
  • 实现Callable接口
  • 线程池创建线程(项目中常用的方式)

1.runnable与callable有什么区别?

  • runnable没有返回值,callable的返回值类型与泛型一样。
  • runnable不能向上抛出异常,只能内部消化,callable可以抛出异常。
  • callable可以用Future、FutureTask获取线程的返回值。

2.线程的run和start有什么区别?

  • run相当于一个普通方法,可以在一个线程中多次执行,而start是开启一个线程,一个线程只能开启一次,多次调用就会抛出异常。
  • run(): 封装了要被线程执行的代码,可以被调用多次。
  • start(): 用来启动线程,通过该线程调用run方法执行run方法中所定义的逻辑代码。start方法只能被调用一次。

4.线程包括哪些状态,状态之间如何变换?

线程的状态可以参考JDK中Thread类中的枚举State。

    public enum State {
        /**
         * Thread state for a thread which has not yet started.
         */
        NEW,

        /**
         * Thread state for a runnable thread.  A thread in the runnable
         * state is executing in the Java virtual machine but it may
         * be waiting for other resources from the operating system
         * such as processor.
         */
        RUNNABLE,

        /**
         * Thread state for a thread blocked waiting for a monitor lock.
         * A thread in the blocked state is waiting for a monitor lock
         * to enter a synchronized block/method or
         * reenter a synchronized block/method after calling
         * {@link Object#wait() Object.wait}.
         */
        BLOCKED,

        /**
         * Thread state for a waiting thread.
         * A thread is in the waiting state due to calling one of the
         * following methods:
         * <ul>
         *   <li>{@link Object#wait() Object.wait} with no timeout</li>
         *   <li>{@link #join() Thread.join} with no timeout</li>
         *   <li>{@link LockSupport#park() LockSupport.park}</li>
         * </ul>
         *
         * <p>A thread in the waiting state is waiting for another thread to
         * perform a particular action.
         *
         * For example, a thread that has called {@code Object.wait()}
         * on an object is waiting for another thread to call
         * {@code Object.notify()} or {@code Object.notifyAll()} on
         * that object. A thread that has called {@code Thread.join()}
         * is waiting for a specified thread to terminate.
         */
        WAITING,

        /**
         * Thread state for a waiting thread with a specified waiting time.
         * A thread is in the timed waiting state due to calling one of
         * the following methods with a specified positive waiting time:
         * <ul>
         *   <li>{@link #sleep Thread.sleep}</li>
         *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
         *   <li>{@link #join(long) Thread.join} with timeout</li>
         *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
         *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
         * </ul>
         */
        TIMED_WAITING,

        /**
         * Thread state for a terminated thread.
         * The thread has completed execution.
         */
        TERMINATED;
    }

简化:

1.线程的6种状态

  1. 新建(new)。
  2. 可执行(runnable)。
  3. 阻塞(blocked)。
  4. 等待(waiting)。
  5. 时间等待(timed_waiting)。
  6. 终止(terminated)。

2.线程状态之间的变化

1.创建线程对象是新建状态。

2.调用start()方法转变为可执行状态。

3.线程获取到了CPU的执行权,执行结束是终止状态。

4.在可执行状态的过程中,如果没有获取到CPU的执行权,可能会切换其它的状态。

(*).如果没有获取到锁(synchronized或lock)进入阻塞状态,获得锁再切换为可执行状态。

(*).如果线程调用了wait()方法进入等待状态,其它线程调用notify()唤醒后可切换为可执行状态。

(*).如果线程调用了sleep()方法,进入计时等待状态,到时间后可切换为可执行状态。

* 表示没有先后顺序

5.新建T1、T2、T3三个线程,如何保证它们按顺序执行?

可以使用线程中的join方法解决。

相关推荐
Algorithm15762 分钟前
k3s主从节点设置详细流程
java·k8s
萧鼎6 分钟前
从零开始构建:Python自定义脚本自动化你的日常任务
开发语言·python·自动化
API1997010811010 分钟前
VVIC商品详情接口技术解析与实战代码示例
开发语言·python·json·php
zhooyu17 分钟前
C++和OpenGL实现3D游戏编程【连载14】——VBO、VAO和EBO应用
开发语言·c++·游戏·游戏程序·游戏策划
QuantumStack23 分钟前
【C++ 真题】B2003 输出第二个整数
开发语言·c++·算法
小七蒙恩25 分钟前
Java面试宝典-WEB学习
java·前端·面试
椰椰椰耶27 分钟前
【Spring】Spring MVC的项目准备和连接建立
java·spring·mvc
风车带走过往36 分钟前
Jenkins pipeline语法笔记
java·servlet·jenkins
惜.己43 分钟前
js操作元素的其他操作(4个案例+效果图+代码)
开发语言·前端·javascript·css·vscode·html·html5
荔枝爱编程1 小时前
《小白:深入解析 Spring 事务与 MySQL 事务》
java·后端·mysql