Java面试_并发编程_线程基础

news2024/11/19 0:36:10

Java面试_并发编程_线程基础

  • 线程基础
    • 线程和进程的区别(出现频率: 3⭐)
    • 并行和并发的区别(出现频率: 2⭐)
    • 线程的创建(出现频率: 4⭐)
    • 线程的状态(出现频率: 4⭐)
    • 让线程按顺序执行(出现频率: 3⭐)
    • notify()和notifyAll()有什么区别(出现频率: 2⭐)
    • wait方法和sleep方法的区别(出现频率: 3⭐)
    • 停止正在运行的线程(出现频率: 2⭐)
  • 来源
  • Gitee地址

线程基础

线程和进程的区别(出现频率: 3⭐)

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

并行和并发的区别(出现频率: 2⭐)

  • 并发是单个CPU同时执行多个线程
  • 并行是多个CPU同时执行多个线程

在这里插入图片描述

线程的创建(出现频率: 4⭐)

创建线程的方式

  • 继承Thread类
  • 实现runnable接口
  • 实现callable接口
  • 线程池创建线程(项目中使用方式)

runnable和callable有什么区别

  • Runnable接口的run方法没有返回值
  • Callable接口的call方法有返回值, 需要FutureTask获取结果
  • Callable接口的call方法允许抛出异常; 而Runnable接口的run方法的异常只能在内部消化, 不能继续上抛

run()和start()有什么区别

  • start(): 用来启动线程, 通过该线程调用run方法中所定义的逻辑代码. start方法只能被调用一次
  • run(): 正常调用方法, 封装了要被线程执行的代码, 可以被调用多次

线程的状态(出现频率: 4⭐)

线程的状态

  • 新建(new)
  • 可运行(runnable)
  • 阻塞(blocked)
  • 等待(waiting)
  • 时间等待(timed_waiting)
  • 终止(terminated)

线程状态之间的变化

  • 创建线程对象是新建状态
  • 调用了start()方法变为可执行状态
  • 线程获取到了CPU的执行权, 执行结束是终止状态
  • 在可执行状态的过程中, 如果没有获取CPU的执行权, 可能会切换为其他状态
    • 如果没有获取锁(synchronized或lock)进入阻塞状态, 获得锁再切换为可执行状态
    • 如果线程调用了wait()方法进入等待状态, 其他线程调用notify()唤醒后可切换为可执行状态
    • 如果线程调用了sleep()方法, 进入计时等待状态, 到时间后可切换为可执行状态

让线程按顺序执行(出现频率: 3⭐)

使用join()方法

public class JoinTest {
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            System.out.println("t1");
        });
        Thread t2 = new Thread(() -> {
            try {
                // 当t1线程执行完毕后, 线程继续执行
                t1.join();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("t2");
        });
        Thread t3 = new Thread(() -> {
            try {
                // 当t2线程执行完毕后, 线程继续执行
                t2.join();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("t3");
        });
        t1.start();
        t2.start();
        t3.start();
    }
}

notify()和notifyAll()有什么区别(出现频率: 2⭐)

  • notifyAll(): 唤醒所有wait的线程
  • notify(): 随机唤醒一个wait的线程
public class notifyAndNotifyAllTest {
    static Object lock = new Object();

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            synchronized (lock) {
                System.out.println(Thread.currentThread().getName() + "...waiting...");
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println(Thread.currentThread().getName() + "...被唤醒了...");
            }
        }, "t1");
        Thread t2 = new Thread(() -> {
            synchronized (lock) {
                System.out.println(Thread.currentThread().getName() + "...waiting...");
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println(Thread.currentThread().getName() + "...被唤醒了...");
            }
        }, "t2");

        t1.start();
        t2.start();

        Thread.sleep(2000);

        synchronized (lock) {
            // lock.notify(); // 随机唤醒一个wait线程
            lock.notifyAll(); // 唤醒所有wait的线程
        }
    }
}

wait方法和sleep方法的区别(出现频率: 3⭐)

共同点

  • wait(), wait(long)和sleep(long)的效果都是让当前线程暂时放弃CPU的使用权, 进入阻塞状态

不同点

  1. 方法归属不同
    • sleep(long)是Thread的静态方法
    • wait(), wait(long)都是Object的成员方法, 每个对象都有
  2. 醒来时机不同
    • 执行sleep(long)和wait(long)的线程都会在等待相应毫秒后醒来
    • wait(long)和wait()还可以被notify()唤醒, wait()如果不唤醒就一直等待
    • 他们都可以被打断唤醒
  3. 锁特性不同
    • wait方法的调用必须先获取wait对象的锁, 而sleep无此限制
    • wait方法执行后会释放对象锁, 允许其他线程获得该对象锁
    • sleep如果在synchronized代码块中执行, 并不会释放对象锁

停止正在运行的线程(出现频率: 2⭐)

  • 使用退出标志, 是线程正常退出, 也就是当run方法完成后线程终止
    public class InterruptDemo extends Thread{
    
        volatile boolean flag = false; // 线程执行的退出标记
    
        @Override
        public void run() {
            while(!flag)
            {
                System.out.println("MyThread...run...");
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    
        public static void main(String[] args) throws InterruptedException {
    
            // 创建MyThread对象
            InterruptDemo t1 = new InterruptDemo();
            t1.start();
    
            // 主线程休眠6秒
            Thread.sleep(6000);
    
            // 更改标记为true
            t1.flag = true;
        }
    
    }
    
  • 使用stop方法强行终止(不推荐, 方法已作废)
  • 使用interrupt方法中断线程
    • 打断阻塞的线程(sleep, wait, join)的线程, 线程会抛出InterruptedException异常
    • 打断正常的线程, 可以根据打断状态来标记是否退出线程
    public class InterruptDemo02 {
        public static void main(String[] args)      throws InterruptedException {
            // // 1. 打断阻塞的线程
            // Thread t1 = new Thread(() -> {
            //     System.out.println("t1正在运行...     ");
            //     try {
            //         Thread.sleep(5000);
            //     } catch (InterruptedException e) {
            //         throw new RuntimeException(e);
            //     }
            // }, "t1");
            // t1.start();
            // Thread.sleep(500);
            // t1.interrupt();
            // System.out.println(t1.isInterrupted     ());
    
            // 2. 打断阻塞的线程
            Thread t2 = new Thread(() -> {
                while(true)
                {
                    Thread current = Thread.     currentThread();
                    boolean interrupted = current.     isInterrupted();
                    if(interrupted){
                        System.out.println("打断状态     : "+interrupted);
                        break;
                    }
                }
            }, "t2");
            t2.start();
            Thread.sleep(500);
            t2.interrupt();
            System.out.println(t2.isInterrupted());
        }
    }
    

来源

黑马程序员. 新版Java面试专题视频教程
小林coding. 图解系统-进程管理

Gitee地址

https://gitee.com/Y_cen/java-interview

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1019785.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ubuntu下 Docker、Docker Compose 的安装教程

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。 Docker Compose是用于定义…

springboot班级综合测评管理系统springboot005

大家好✌!我是CZ淡陌。一名专注以理论为基础实战为主的技术博主,将再这里为大家分享优质的实战项目,本人在Java毕业设计领域有多年的经验,陆续会更新更多优质的Java实战项目,希望你能有所收获,少走一些弯路…

优思学院|六西格玛与敏捷管理两者有何不同?

如果你正在寻找提高组织流程和降低缺陷或错误的方法,六西格玛和敏捷是两种你可能会考虑的方法。这两种方法有着不同的重点和应用领域。在这篇文章中,我们将深入研究六西格玛和敏捷,并探讨它们之间的差异。 什么是六西格玛? 六西…

MySQL数据库索引优化难点与面试点

MySQL数据库索引优化难点与面试点 什么是MySQL索引? 索引的MySQL官方定义:索引是帮助MySQL快速获取数据的数据结构。 动力节点原文: MysQL官方对于索引的定义:索引是帮助MySQL高效获取数据的数据结构。 MysQL在存储数据之外,数据…

Qt5开发及实例V2.0-第二章Qt模板库工具类及控件

Qt5开发及实例V2.0-第二章Qt模板库工具类及控件 第2章 Qt 5模板库、工具类及控件2.1 字符串类2.1.1 操作字符串2.1.2 查询字符串数据2.1.3 字符串的转换 2.2 容器类2.2.1 QList类、QLinkedList类和QVector类2.2.2 QMap类和QHash类 2.3 QVariant类2.4 算法及正则表达式2.4.1 Qt …

Spring编程常见错误50例-Spring Bean依赖注入常见错误(下)

Value没有注入预期的值 问题 对于Value可以装配多种类型的数据: 装配对象: Value("#{student}") private Student student;Bean public Student student(){Student student createStudent(1, "xie");return student; }装配字符…

【Nuxt3】Vue3 + Element-plus 打包后报错 @popperjs/core

问题: 更新 Element-plus 后,运行时需要安装 popperjs/core 依赖。 如果正常执行 npm install popperjs/core ,那么,打包时,就会出现下面报错。 Named export ‘placements’ not found. The requested module ‘poppe…

Python | 为FastAPI后端服务添加API Key认证(分别基于路径传参和header两种方式且swagger文档友好支持)

文章目录 01 前言02 路径传参方式添加API Key2.1 完整代码2.2 请求示例2.3 swagger文档测试 03 请求头Header方式传入API Key(推荐)3.1 完整代码3.2 请求示例3.3 swagger文档测试 01 前言 FastAPI,如其名所示,是一个极为高效的框…

云计算的未来:云原生架构和自动化运维的崭露头角

文章目录 云计算的演进云原生架构1. 容器化2. 微服务3. 自动化部署和扩展4. 故障恢复 自动化运维1. 基础设施即代码(IaC)2. 运维自动化示例:使用Ansible自动化配置管理 3. 自动化监控和报警 未来展望1. 更多的自动化2. 多云混合云3. 边缘计算…

华为+苹果的“科技春晚”背后,“自主创新+实在技术”遥遥领先!

过去的24小时里,科技春晚迎来“双主角”:12日下午,华为发布会,13日凌晨,苹果发布会。 尽管苹果一向以其创新和高端的形象而闻名,但与昔日苹果发布会后有关新品的词条霸屏微博热搜不同,当天在发…

初步了解华为的MTL(市场到线索)流程的基本概念和来龙去脉

前两天,有读者给华研荟发私信,说在学习华为资料的时候看到华为有一个MTL流程,想了解下这个MTL流程和LTC流程有什么区别?既然有了LTC流程,为什么还要MTL流程呢? 为此,今天华研荟给大家简要介绍华…

让电子制造厂提高生产率的方法,学会受用终生!

在现代工业领域,工厂的生产运营离不开复杂的设备和关键的基础设施。然而,工厂在日常运营中常常面临着各种风险,其中之一就是水浸事件。 水浸监控不仅仅是一种反应性的措施,更是一种预防性的安全策略。通过使用高度先进的传感技术和…

前端使用H5中draggable实现拖拽排序效果 两种实现效果

文章目录 一、实现效果①1、实现代码2、效果演示 二、实现效果②1.实现代码2.效果演示 一、实现效果① 将一个节点拖到另一个节点之前或之后 1、实现代码 <!DOCTYPE html> <style>* {padding: 0;margin: 0;}body {display: flex;width: 100%;height: 100vh;just…

Matlab中关于 : 的使用

设&#xff0c;mat 这个矩阵的规格是 n*m&#xff0c;temp mat( i , j ) 矩阵的行和列的下标从1开始 在这个矩阵中&#xff0c;a:b 代表的含义是范围是从 a--b 则&#xff0c;当 a 和 b 被省略时&#xff0c;代表的范围就是最大范围&#xff08;1--n&#xff09; or &#…

卡奥斯第二届1024程序员节重磅预告!

一场属于程序员的狂欢! 第二届卡奥斯1024程序员节重磅来袭。 提前做好活动攻略&#xff0c;欢欢喜喜大奖抱回家&#xff01; 本次活动设置4个活动分会场: 低代码分会场、开源分会场、知识分会场和产品分会场&#xff0c;共12个奖项&#xff0c;1100多个奖品&#xff0c;雷神9…

IP归属地在金融行业的应用场景

IP归属地查询在各大行业当中的利用率可以说非常的高了&#xff0c;提供了各种的保障&#xff0c;比如安全保障、数据保障、性能保障等等。今天我就来详细说一说IP归属地在金融行业的应用场景有哪些&#xff1f; 用途一&#xff1a;通过解析用户IP地址所处的区县位置与表单填写位…

Re-Learn Linux Part1

1. Linux的目录结构 在Linux文件系统中有两个特殊的目录&#xff1a; 一个用户所在的工作目录&#xff0c;也叫当前目录&#xff0c;可以使用一个点 . 来表示&#xff1b;另一个是当前目录的上一级目录&#xff0c;也叫父目录&#xff0c;可以使用两个点 .. 来表示。 . &#…

关于激光探测器光斑质心算法在FPGA硬件的设计

目录 0引言 1CCD采集图像质心算法 2基于FPGA的图像质心算法 3仿真结果与分析 4结论 0引言 在一些姿态检测的实际应用中&#xff0c;需要在被测对象上安装激光探测器[1]&#xff0c;利用CCD相机捕捉激光光斑来检测观测对象的实际情况&#xff0c;光斑图像质心坐标的提取是图…

机器学习——SVM(支持向量机)

0、前言&#xff1a; SVM应用&#xff1a;主要针对小样本数据进行学习、分类和回归&#xff08;预测&#xff09;&#xff0c;能解决神经网络不能解决的过学习问题&#xff0c;有很好的泛化能力。&#xff08;注意&#xff1a;SVM算法的数学原理涉及知识点比较多&#xff0c;所…

grep多行匹配以及一些问题

测试文本, a.txt 123 456789这里是简单的文本 使用grep多行匹配 grep -Pzo "123\s456" a.txt-P: 启用Perl正则表达式模式。 -z: 允许多行匹配&#xff0c;即使匹配跨越了换行符的行。 -o: 只输出匹配的部分。 这里能匹配到 123 456但是有的时候也匹配不到&#…