面试题003-Java-Java多线程(上)

面试题003-Java-Java多线程(上)

目录

  • 面试题003-Java-Java多线程(上)
    • 题目自测
    • 题目答案
      • 1. 什么是线程和进程? 线程与进程的关系和区别?
      • 2. 为什么要使用多线程?
      • 3. 什么是线程上下文切换?
      • 4. 什么是线程死锁? 如何避免死锁?
      • 5. 乐观锁和悲观锁了解么?如何实现乐观锁?
      • 6. 说说 sleep() 方法和 wait() 方法区别和共同点?
      • 7. 讲一下 JMM(Java 内存模型) ?
      • 8. Java 内存区域和 JMM 有何区别?
      • 9. Java中如何创建线程?
      • 10. 实现Runnable接口和实现Callable接口的区别?
    • 参考资料

题目自测

  • 1. 什么是线程和进程? 线程与进程的关系和区别?
  • 2. 为什么要使用多线程?
  • 3. 什么是线程上下文切换?
  • 4. 什么是线程死锁?如何避免死锁?
  • 5. 乐观锁和悲观锁了解么?如何实现乐观锁?
  • 6. 说说 sleep() 方法和 wait() 方法区别和共同点?
  • 7. 讲一下 JMM(Java 内存模型) ?
  • 8. Java 内存区域和 JMM 有何区别?
  • 9. Java中如何创建线程?
  • 10. 实现Runnable接口和实现Callable接口的区别?

题目答案

1. 什么是线程和进程? 线程与进程的关系和区别?

答:进程是程序一次执行的过程,系统运行一个程序即是一个进程从创建、运行到消亡的过程。
线程是程序执行的最小单位,一个进程可以产生多个线程,线程可以共享其进程的资源。
线程与进程的关系:一个进程可以包含多个线程,线程是进程的一部分。线程共享进程的资源,进程之间相互独立。
线程和进程的区别:进程有独立的内存空间,线程共享进程的内存空间。进程间通信复杂,线程可以通过共享内存进行通信速度快。进程独立性强安全性高,线程独立性相对较弱,一个线程崩溃可能导致整个程序崩溃。

2. 为什么要使用多线程?

答:提高性能和响应速度,多线程可以使程序同时执行多个任务,从而充分利用多核处理器的能力,提高程序的执行效率。如一个多线程的Web服务器可以同时处理多个客户端请求。
更好的利用资源,在多核处理器环境下,多线程可以让多个CPU核心并行工作。在单核处理器上,多线程可以让某些任务等待I/O操作时执行其他任务,从而更高效的利用CPU时间。

3. 什么是线程上下文切换?

答:线程上下文切换是指操作系统在多线程任务处理中,将CPU从一个线程切换到另外一个线程的过程。在这个过程中,操作系统需要保存当前线程的状态也称上下文(程序计数器、堆栈信息等),然后加载另外一个线程的状态,以便该线程可以继续执行。
出现线程切换的情况:

  • 时间片用完:操作系统将CPU时间划分为多个时间片,每个线程会被分配一个固定的时间片,当时间片用完,操作系统会进行上下文切换,让其他线程活动CPU时间。
  • 阻塞操作:当线程执行阻塞操作(如等待I/O操作完成、执行slepp()、wait()、等待同步锁等)时,它会主动放弃CPU的使用权,进入阻塞状态。
  • 中断处理:当硬件发生中断时(如键盘输入、定时器触发),操作系统需要处理当前线程的执行,以处理中断。
  • 线程优先级变化:当某个线程的优先级发生变化时(如通过调用线程的setPriority()方法),作系统可能会进行上下文切换,将CPU分配给这个高优先级的线程。这种调度策略称为抢占式调度。

4. 什么是线程死锁? 如何避免死锁?

答:线程死锁是指两个或多个线程在执行的过程中,因相互持有对方所需要的资源而处于等待状态,导致所有线程都无法执行继续的情况。具体表现为,每个线程都在等待其他线程释放资源,而每个线程又都持有其他线程所需的资源,从而形成一个等待环路,造成永久阻塞。
死锁的四个必要条件:

  • 互斥:至少有一个资源必须是非共享的,即一次只能由一个线程使用。
  • 占有且等待:个线程已经持有至少一个资源,同时等待获取其他被其他线程持有的资源。
  • 不可剥夺:资源不能被强行剥夺,必须由持有线程显示释放。
  • 循环等待:发生死锁时,涉及的所有线程必定存在一个循环等待资源的链。
    避免死锁的方法:
  • 资源有序分配:为资源分配一个全局顺序,所有线程按照这个顺序请求资源,可以避免发生循环等待。
  • 避免嵌套锁:尽量避免一个线程同时持有多个锁,减少嵌套锁的使用。
  • 限时等待:如无法在指定时间内获取锁,就放弃请求并释放已经持有的锁。
  • 死锁检测和恢复:使用JVM提供的工具或第三方库来监控和检测死锁。
  • 资源预先分配:确保线程在开始执行前就已经获取到所需的所有资源。

5. 乐观锁和悲观锁了解么?如何实现乐观锁?

答:乐观锁和悲观锁这两种锁策略用于解决并发控制问题。
悲观锁是一种假设最坏情况的锁策略,每次在去访问数据时都会认为别人会修改,所以在每次访问数据时都会上锁,这样别人在拿这个数据就会阻塞直到它拿到锁。Java中悲观锁是通过synchronized关键字或Lock接口来实现。
乐观锁是一种假设最好情况的锁策略,每次在去访问数据时都认为别人不会修改,所以不会上锁,但是在修改的时候会去判断有没有人修改这个数据。Java中通常通过版本号机制或者CAS算法来实现。
实现乐观锁的方式:

  • 版本号:在数据库表中添加一个版本号字段,每次更新数据时版本号加1。在更新数据时,将当前版本号作为条件之一进行更新,如果版本号不匹配,则说明数据已经被其他线程修改。
  • CAS:使用一个预期值和要更新的变量值进行比较,两值相等才会进行更新

6. 说说 sleep() 方法和 wait() 方法区别和共同点?

答:slepp()和wait()都可以暂停线程的执行。
两者的区别:

  • sleep() 是 Thread 类的静态方法,wait() 是 Object类的实例方法。
  • sleep() 不会释放锁,wait() 会释放锁进入等待状态、直到被唤醒。
  • sleep() 在指定的时间到期后会自动唤醒,wait() 需要 notify()/notifyAll()方法来唤醒。
  • sleep() 可以在任何地方使用,wait() 必须在同步块或者同步方法中调用。

7. 讲一下 JMM(Java 内存模型) ?

答:Java内存模型是Java虚拟机规范的一部分,它定义了在多线程环境下,Java程序中变量的访问方式。JMM是一种抽象概念,它屏蔽了不同硬件和操作系统内存访问的差异,为Java程序提供了一致的内存访问效果。
JMM分为主内存和工作内存,主内存是所有线程共享的区域,对应于JVM内存区域中的堆。工作内存是JMM抽象的概念,并非真实存在,它对应于JVM中的栈,线程对变量的所有操作都必须在工作内存中进行,不能直接操作主内存中的数据。

8. Java 内存区域和 JMM 有何区别?

答:Java内存区域侧重于JVM如何管理和划分运行时内存区域。Java内存区域有堆、方法区、虚拟机栈、程序计数器、本地方法栈。
JMM侧重于多线程环境下线程与主存之间的交互关系以及变量的访问规则。

9. Java中如何创建线程?

答:Java中创建线程的方式有很多,如继承Thread类、实现Runnable接口、实现Callable接口、使用ExecutorService线程池等等。

  • 继承Thread类:创建一个类来继承Thread类,重写它的run()方法。然后通过创建这个类的实例来创建新的线程,通过调用类实例的start()方法来启动线程。
    class MyThread extends Thread {  
        public void run() {  
            System.out.println("线程运行中");  
        }  
    }  
      
    public class ThreadExample {  
        public static void main(String[] args) {  
            MyThread t = new MyThread();  
            t.start(); // 启动线程  
        }  
    }
    
  • 实现Runnable接口:创建一个类来实现Runnable接口,实现它的run()方法,然后创建Thread类的实例,将Runnable接口实现类的实例作为构造器参数传递,调用Thread类的实例的start()方法启动线程。
    class MyThread extends Thread {  
        public void run() {  
            System.out.println("线程运行中");  
        }  
    }  
      
    public class ThreadExample {  
        public static void main(String[] args) {  
            MyThread t = new MyThread();  
            t.start(); // 启动线程  
        }  
    }
    
  • 实现Callable接口:创建一个Callable接口的实现类,并实现call()方法。然后创建Callable实现类的实例,使用FutureTask类来包装Callable对象,使用FutureTask对象作为Thread对象的target创建并启动新线程,调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。
    class MyCallable implements Callable<String> {  
        public String call() throws Exception {  
            return "线程执行结果";  
        }  
    }  
    
    public class CallableExample {  
        public static void main(String[] args) throws Exception {  
            MyCallable callable = new MyCallable();
            FutureTask<String> futureTask = new FutureTask<>(callable);
            new Thread(futureTask).start();
            System.out.println(futureTask.get()); // 获取结果
        }  
    }
    

10. 实现Runnable接口和实现Callable接口的区别?

答:他们主要的区别体现在方法签名和返回值、异常处理和提交与执行方式上。

  • 方法签名和返回值:Runnable的run()方法有返回值,Callable的call()方法有返回值。
  • 异常处理:run()方法不能抛出受检异常,只能处理运行时异常。call()方法可以声明抛出异常。
  • 提交和执行:Runnable通过Thread或ExecutorService执行。Callable通过ExcutroService执行,并返回Future对象以获取结果。

参考资料

  • JavaGuide
  • 牛客网-Java面试宝典

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Windows如何安装并启动Nginx

0、前言 Nginx 是一款高性能、轻量级的Web服务器和反向代理服务器&#xff0c;广泛应用于互联网领域。它以其高效稳定、内存占用少和丰富的模块化设计而受到开发者们的青睐。 在实际使用过程中&#xff0c;我们多数时候会在Linux系统上运行Nginx&#xff0c;但实际上&#xff…

国产强大免费WAF, 社区版雷池动态防护介绍

雷池WAF&#xff0c;基于智能语义分析的下一代 Web 应用防火墙 使用情况 我司于2023年4月23日对雷池进行测试&#xff0c;测试一个月后&#xff0c;于2023年5月24日对雷池进行正式切换&#xff0c;此时版本为1.5.1。 里程碑纪念 后续一直跟随雷池进行版本升级&#xff0c;当前…

秋招力扣刷题——从前序与中序遍历序列构造二叉树

一、题目要求 给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵树的中序遍历&#xff0c;请构造二叉树并返回其根节点。 二、解法思路 根据二叉树的遍历结构重构二叉树&#xff0c;至少两种遍历方式结合&…

kettle生成uuid32位——kettle开发44

生成UUID: UUID是由一组字符组成&#xff0c;通常呈现为32位的十六进制数&#xff0c; 如 "550e8400-e29b-41d4-a716-446655440000" 目标&#xff1a; 生成的UUID是34位的&#xff0c;我们去掉-&#xff0c;转换为正常的32位 实现&#xff1a;

Android TextView的属性与用法

文本控件包括TextView、EditText、AutoCompleteTextView、CheckedTextView、MultiAutoCompleteTextView、TextInputLayout等&#xff0c;其中TextView、EditText是最基本最重要的文本控件&#xff0c;是必须要掌握的文本控件。 1.TextView TextView控件用于显示文本信息&…

Three.js机器人与星系动态场景(二):强化三维空间认识

在上篇博客中介绍了如何快速利用react搭建three.js平台&#xff0c;并实现3D模型的可视化。本文将在上一篇的基础上强化坐标系的概念。引入AxesHelper辅助工具及文本绘制工具&#xff0c;带你快速理解camer、坐标系、position、可视区域。 Three.js机器人与星系动态场景&#x…

红酒的秘密花园:探索葡萄的种植艺术

在远离城市喧嚣的某个角落&#xff0c;隐藏着一座神秘的红酒秘密花园。这里&#xff0c;葡萄藤缠绵交织&#xff0c;绿叶间闪烁着晶莹的露珠&#xff0c;仿佛在诉说着关于红酒与葡萄种植艺术的古老传说。今天&#xff0c;就让我们一起走进这片神秘的花园&#xff0c;探寻葡萄种…

Mysql查询IFNULL和想象的不一样

select sum(ifnull(a,0)) aaa,ifnull(sum(a),0) bbb from (select g.goodsid a from goods g where g.goodsid 601 ) tmp #注意 goodsid 601 的不存在 ​​​ 返回的结果和想象中不同&#xff0c;解释如下 在您SQL查询中&#xff0c;创建了一个子查询&#xff08;别名为tmp&a…

FEBLESS SAP软件对芯片设计企业的重要性

在集成电路(IC)设计行业&#xff0c;无晶圆厂模式(Fabless)企业专注于芯片的设计和销售&#xff0c;而将制造和封装测试外包给专业的代工厂和封测厂。Fabless模式下&#xff0c;企业面临着复杂的供应链管理和项目协同挑战&#xff0c;而SAP软件作为一款成熟的企业资源规划(ERP)…

iiiiiiiiiiiiiiiiiiiiiiiiiio_contexttttttttttttttttttttttttt

https://www.cnblogs.com/bwbfight/p/17594353.html 谈一谈linux下线程池 - 白伟碧一些小心得 - 博客园 (cnblogs.com) 谈一谈linux下线程池 - 白伟碧一些小心得 - 博客园 (cnblogs.com) https://www.cnblogs.com/bwbfight/p/10901574.html 前面的设计&#xff0c;我们对asio…

Kafka集群安装部署

简介 Kafka是一款分布式的、去中心化的、高吞吐低延迟、订阅模式的消息队列系统。 同RabbitMQ一样&#xff0c;Kafka也是消息队列。不过RabbitMQ多用于后端系统&#xff0c;因其更加专注于消息的延迟和容错。 Kafka多用于大数据体系&#xff0c;因其更加专注于数据的吞吐能力…

AI网络爬虫006:从当当网批量获取图书信息

文章目录 一、目标二、输入内容三、输出内容一、目标 用户输入一个图书名称,然后程序自动从当当网批量获取图书信息 查看相关元素在源代码中的位置: 二、输入内容 第一步:在deepseek中输入提示词: 你是一个Python爬虫专家,一步步的思考,完成以下网页爬取的Python脚本任…

WEB攻防-XSS跨站反射型存储型DOM型标签闭合输入输出JS代码解析

文章目录 XSS跨站-输入输出-原理&分类&闭合XSS跨站-分类测试-反射&存储&DOM反射型XSS存储型XSSDOM-base型XSS XSS跨站-输入输出-原理&分类&闭合 漏洞原理&#xff1a;接受输入数据&#xff0c;输出显示数据后解析执行 基础类型&#xff1a;反射(非持续…

ffmpeg下载/配置环境/测试

一、下载 1、访问FFmpeg官方网站下载页面&#xff1a;FFmpeg Download Page&#xff1b; 2、选择适合Windows的版本&#xff08;将鼠标移动到windows端&#xff09;。通常&#xff0c;你会找到“Windows builds from gyan.dev”或者“BtbN GitHub Releases”等选项&#xff0…

Java的异常处理体系

目录 异常处理1、Java的异常类层次结构2、try-catch-finally 使用注意事项3、在Web应用中如何实现全局异常处理机制 异常处理 1、Java的异常类层次结构 其中Error表示程序运行错误 常见的错误类型有&#xff1a; OutOfMemoryError (内存溢出错误) StackOverFlowError (栈内存溢…

ctfshow-web入门-命令执行(web118详解)Linux 内置变量与Bash切片

输入数字和小写字母&#xff0c;回显 evil input 查看源码&#xff0c;发现这里会将提交的参数 code 传给 system 函数 使用 burpsuite 抓包进行单个字符的模糊测试 fuzz&#xff1a; 发现过滤掉了数字和小写字母以及一些符号&#xff0c;下面框起来的部分是可用的 结合题目提…

vue2使用use注册自定义指令实现输入控制与快捷复制

使用场景 在一些form表单填写内容的时候&#xff0c;要限制输入的内容必须是数值、浮点型&#xff0c;本来el-input-number就可以实现&#xff0c;但是它本身带那个数值控制操作&#xff0c;等一系列感觉不舒服的地方。如果只是使用el-input该多好&#xff0c;只要监听一下输入…

爬虫笔记20——票星球抢票脚本的实现

以下内容仅供交流学习使用&#xff01;&#xff01;&#xff01; 思路分析 前面的爬虫笔记一步一步走过来我们的技术水平也有了较大的提升了&#xff0c;现在我们来进行一下票星球抢票实战项目&#xff0c;实现票星球的自动抢票。 我们打开票星球的移动端页面&#xff0c;分…

身份证OCR识别的深度解读

引言 随着信息技术的飞速发展&#xff0c;光学字符识别&#xff08;OCR&#xff09;技术在各个领域得到了广泛应用。身份证OCR识别&#xff0c;作为OCR技术的一个重要分支&#xff0c;以其高效、准确的特点&#xff0c;在身份验证、信息录入等方面发挥着重要作用。本文将深入解…

【Linux】Linux用户,用户组,其他人

1.文件拥有者 初次接触Linux的朋友大概会觉得很怪异&#xff0c;怎么“Linux有这么多用户&#xff0c;还分什么用户组&#xff0c;有什用呢&#xff1f;”&#xff0c;这个“用户与用户组”的功能可是相当健全而且好用的一个安全防护措施。 怎么说呢&#xff1f;由于Linux是个…