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方法解决。

相关推荐
咕白m6251 小时前
Java 实现 Excel 转 HTML:完整示例
java
RealPluto2 小时前
Spring AOP 失效排查
java·spring
码路飞2 小时前
热榜全是 OpenClaw,但我用 50 行 Python 就造了个桌面 AI Agent 🤖
java·javascript
Nyarlathotep01133 小时前
LinkedList源码分析
java·后端
用户8307196840823 小时前
Java 告别繁琐数据统计代码!MySQL 8 窗口函数真香
java·sql·mysql
带刺的坐椅3 小时前
SolonCode v0.0.20 发布 - 编程智能体(新增子代理和浏览器能力)
java·ai·agent·solon·solon-ai·claude-code·openclaw
会员源码网5 小时前
数字格式化陷阱:如何优雅处理 NumberFormatException
java
孔明click335 小时前
Sa-Token v1.45.0 发布 🚀,正式支持 Spring Boot 4、新增 Jackson3/Snack4 插件适配
java·sa-token·开源·springboot·登录·权限认证
程序猿阿越5 小时前
Kafka4源码(二)创建Topic
java·后端·源码阅读
悟空码字6 小时前
Spring Boot 整合 MongoDB 最佳实践:CRUD、分页、事务、索引全覆盖
java·spring boot·后端