Java并发复习

news2024/9/23 23:06:39

Java基础

1. 为什么要使用并发编程?

一般我们工作的电脑都有多核,我们创建多个线程,然后操作系统可以将多个线程分配给不同的CPU去执行,每个CPU执行一个线程,这样就提高了CPU使用效率。

在网络购物中,我们买了一个东西的同时,需要减库存,生成订单等等这些操作,就可以进行拆分利用多线程的技术完成。面对复杂业务模型,并行程序串行会比程序更适应业务需求,而并发编程更能吻合这种业务拆分。

->

  • 充分利用多核CPU的计算能力;
  • 更好进行业务拆分,提升应用性能

2. 并发编程有什么缺点

并发编程并不能总是能提高程序运行速度,而且可能遇到很多问题:
内存泄漏,上下文切换,线程安全,死锁等问题。

3.并发编程三个必要因素是什么?

  • 原子性:可以这么理解:这里的原子是一个不可以再分割的颗粒。->一个或多个操作要么全部完成,否则全部失败
  • 可见性:一个线程对共享变量的修改,其他线程能够立即看到(sychronized,volatile)
  • 有序性:程序执行的顺序按照代码的先后顺序执行。(处理器看可能会对指令进行重排序->保证在处理器看到的串行语义一致)

4.在Java程序中怎么保证多线程的运行安全?

出现线程安全问题的原因一般都是三个原因:

  • 线程切换带来的原子性问题
    ->解决方法:使用多线程之间同步synchronized或使用锁(lock).
  • 缓存导致的可见性问题
    ->solution: sychronized,volatile,LOCK,可以解决可见性问题。、
  • 重排序优化带来的有序性问题
    ->solution:Happen-Before规则则可以解决 有序性问题

Happen-Before规则如下:

  • 程序次序规则:在一个线程内,按照程序控制流,书写在前面的操作先行发生于书写在后面的操作
  • 锁操作:一个unlock操作先行发生于后面对同一个锁的lock操作
  • volatile变量规则:对一个volatile变量的写操作先行发生于后面这个变量的读操作
  • 线程启动规则:Thread对象的start()方法先行发生于此线程的每一个动作
  • 线程终止规则:线程中的所有操作都先行发生于对此线程的终止检测。
  • 线程中断规则:对线程的Interrupt()方法的调用发生于被中断线程的代码检测到中断事件的发生。
  • 对象终结规则:一个对象的初始化完成先行发生于它的finalize()方法的开始

并行和并发的区别

并行:同一时间多个处理器处理多个任务
并发:一个处理器按照时间片轮转法处理多个任务

什么是进程,什么是线程

这里有两个并发,一个是进程的并发,一个是线程 的并发
进程:对运行时的程序进行封装,是系统进行资源分配的基本单位,实现了操作系统的并发;
线程:进程的子任务,是CPU调度的基本单位,用于保证程序的实时性,实现进程内部的并发;

什么是上下文切换?

在多线程编程中,一般线程的个数大于CPU核心的个数,而一个CPU核心在任意时刻只能被一个线程使用,为了能让这些线程都有效的执行,CPU采用的策略是为每个线程分配时间片并轮转的形式。当一个线程 的时间片用完的时候就会重新处于就绪状态让其他线程使用,这个过程就属于一次上下文切换。
上下文切换通常会因为相当可观的处理器i时间来切换线程而消耗大量的CPU时间,在Linux系统中,上下文切换和模式切换的时间消耗是非常少的。

守护线程和用户线程的区别?

  • 用户线程:运行在前台,执行具体的任务,如程序的主线程,连接网络的子线程等都是用户线程
  • 守护线程:运行在后台,为其他前台线程服务
    守护线程在JVM中,是非守护线程的“佣人”,只要所有用户线程都结束运行,守护线程会随JVM一起结束工作。

什么是线程死锁?

  • 死锁是指两个或两个以上的线程 因为竞争资源 或者 由于彼此通信而造成的一种阻塞的现象,若无外力作用,他么都无法推进下去。此时称系统处于死锁状态或系统产生了死锁进程。
  • 多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源别释放。由于线程被无限期地阻塞,因此程序不可能正常终止。
    在这里插入图片描述

Java线程有几种状态,分别是啥

在Java thread state枚举类中定义了6种线程状态,分别是新建状态New,运行态Runnable,阻塞态Blocked,等待态waiting,延迟等待态Tiimed Waiting 和 终止状态Terminated

线程状态如何流转

在这里插入图片描述
新建状态(New)通过start 方法到达 运行状态 (Runnable)
运行状态(Runnable)等待锁进入阻塞状态(Blocked)
获得锁回到运行状态(Runnable)
运行状态(Runnable)等待其他线程通知进入等待状态(Waiting)
收到通知回到运行状态(Runnable)
超时等待(Time Waiting) 同理,但是这个会设置一个时间限制,超过了这个等待的最大时间,线程会自动返回。
结束进入终止状态

Java创建线程的方式

1. 继承Thread类
通过继承Thread类,并重写它的run方法,我们就可以创建一个线程。

  • 首先定义一个类来继承Thread类,重写run方法
  • 然后创建这个子类对象,并调用start方法启动线程
    2. 实现Runnable接口
    通过实现Runnable接口,并实现run方法,也可以创建一个线程。
  • 首先定义一个类实现Runnable接口,并实现run方法。
  • 然后创建Runnable实现类对象,并把它作为target传入Thread的构造函数中
  • 最后调用start方法启动线程。
    3.实现Callable接口,并结合Future实现
  • 首先定义一个Callable的实现类,并实现call方法,call方法是带返回值的。
  • 然后通过FutureTask的构造方法,把这个Callable实现类传进去。
  • 把FutureTask作为Thread类的target,创建Thread线程对象。
  • 通过FutureTask 的get方法获取线程的执行结果

说一下runnable和callable有什么区别

相同点:

  • 都是接口
  • 都可以编写多线程程序
  • 都采用Thread.start()启动程序

主要区别:

  • Runnable接口 run方法无返回值;Callable接口call方法有返回值,是个泛型,和Future,FutureTask配合可以用来获取异步执行的结果
  • Runnable接口 run方法只能抛出运行时异常,且无法捕获处理;Callable接口call方法允许抛出异常,可以获取异常信息 注:Callable接口支持返回执行结果,需要调用FutureTask.get()得到,此方法会阻塞主线程的继续往下执行,如果不调用不会阻塞。

什么是Callable 和 Future ? 什么是FutureTask?

  • Callable接口类似于Runnable,从名字就可以看出来了,但是Runnable不会返回结果,并且无法抛出返回结果的异常,而Callable功能更强大一些,被线程执行后,可以返回值,这个返回值可以被Future拿到,也就是说,Future可以拿到异步执行任务的返回值。【异步执行:执行一个类似于函数的东西,但是不会被这个函数这一行代码阻塞,可以在之后的代码中获取结果或处理任务完成的状态】

sleep()和wait()有什么区别?

两者都可以暂停线程的执行:

  • 类的不同:sleep()是THread线程类的静态方法,wait()是Object类的方法
  • 是否释放锁:sleep()不释放锁;wait()释放锁
  • 用途不同:Wait通常被用于线程间交互/通信,sleep通常被用于暂停执行。
  • 用法不同:wait()方法被调用后,线程不会自动苏醒,需要别的线程调用同一个对象上的notify()或者notifyAll()方法。sleep()方法执行完成后,线程会自动苏醒。或者可以使用wait(long timeout) 超时后,线程会自动苏醒。

为什么线程通信的方法wait(),notify()和notifyAll()被定义在Object类里?

因为Java所有类的都继承了Object,Java想让任何对象都可以作为锁,并且wait(),notify()等方法用于等待对象的锁或者唤醒线程,在Java的线程类中并没有可供所有对象使用的锁,所以任意对象都可调用的方法一定定义在Object类中。
有的人会说,既然是线程放弃对象锁,那也可以把wait()定义在Thread类里面啊,新定义的线程继承于Theread类里面啊,新定义的线程继承于Thread类,也不需要重新定义wait()方法的实现

为什么wait(),notify()和notifyAll()必须在同步方法或者同步块中被调用?

当一个线程需要调用对象的wait()方法的时候,这个线程必须拥有该对象的锁,接着它就会释放这个对象锁并进入等待状态。
知道其他线程调用这个对象上的
notify()方法。
同样的,当一个线程需要调用对象的
notify(
)方法时,它会释放这个对象的锁,以便其他在等待的线程可以得到这个对象锁。
由于所有的这些方法都需要线程持有对象的锁,这样就只能通过同步来实现,所以他们只能在同步方法或者同步块中被调用。

线程的sleep()方法和yield()方法有什么区别?

  1. sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法指挥给相同优先级或更高优先级线程以运行的机会;
  2. 线程执行sleep()方法后转入阻塞(超时等待状态),而执行yield()方法后转入就绪(ready)状态;
  3. sleep()方法声明抛出InterruptedException,而yield()方法没有声明任何异常;
  4. sleep()方法比yield()方法(跟操作系统CPU调度相关) 具有更好的可移植性,通常不建议使用yield()方法来控制并发线程的执行。
    [sleep()方法在Java中明确定义,而且在所有JAVA平台都一致 ,无论在哪个平台使用,sleep()方法都能导致线程暂停指定的时间]
    在某些系统中,yield可能不能短暂放弃CPU ->Expand

如何停止一个正在运行的线程?

1.run()方法完成之后->使用退出标志,是线程正常退出
2.使用stop方法强行终止,但是不推荐这个方法,这是一个过时的方法
3.使用interrupt方法中断线程:这个需要被中断的线程的中断标识位不会因为sleep(),wait()而抹除
需要重复标记->需要有个catch块中不断标记

catch (InterruptedException e) {
                System.out.println("Thread was interrupted during sleep.");
                // 重新中断线程,以确保中断状态被正确标记
                Thread.currentThread().interrupt();
            }

注意:这个线程是否真正中断,需要看操作系统以及JVM的实现

Java中interrupted和 isInterrupted方法的区别?

interrupt:用于中断线程。调用该方法的线程的状态将设置为“中断”状态。
注意:线程中断仅仅是置线程的中断状态位,不会停止线程。需要用户自己去监视线程的状态为并做处理。
interrupted:是静态方法,查看当前中断信号是true还是false并且清除中断信号。如果一个线程被中断了,第一次调用interrupted则返回true,第二次和后面的就返回false了

线程池的拒绝策略有哪些?

AbortPolicy: 该线程是线程池的默认策略。使用该策略时,如果线程队列满了****丢掉这个任务并且抛出RejectedExecutionException异常。
DiscardPolicy :
队列满了,丢弃这个任务,不抛出异常
DiscardOldestPolicy:
丢弃最早将进入队列的任务,再尝试加入队列,移除队头,再让新加入的任务加入队尾
CallerRunsPolicy:
使用此策略,如果添加到线程池失败,那么
主线程会自己去执行该任务,不会等待线程池中的线程去执行。**

CountDownLatch,CyclicBarrier,Semapher,Exchanger说一下:

  • CountDownLatch:倒计数器。允许一个或多个线程等待其他线程完成操作
  • CyclicBarrier:可循环使用(Cyclic)的屏障(Barrier)。让一组线程都到达屏障点的时候,所有被屏障拦截的线程才会运行。
  • Exchanger:是一个用于线程间协作的工具类。Exchanger用于进行线程缉拿的数据交换。它提供了一个同步点,在这个同步点,两个线程可以交换彼此的数据。

CyclicBarrier和CountDownLatch有什么区别?

  • CyclicBarrier是可重用的,其中的线程会等待所有的线程完成任务。CountDownLatch是一次性的,不同的线程在同一个计数器上工作,知道计数器为0.
  • CyclicBarrier面向的是线程数;CountDownLatch面向的是任务数
    这个就是说他们两个都会设置变量,假如变量是10,如果CyclicBarrier中的线程到达barrier-> -1
    CountDownLatch中的任务完成->-1

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

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

相关文章

52. 两个链表的第一个公共节点

comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9%A2%9852.%20%E4%B8%A4%E4%B8%AA%E9%93%BE%E8%A1%A8%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%85%AC%E5%85%B1%E8%8A%82%E7%82%B9/README.md 面试题 52. 两…

逆向基础一阶段检测-2

做题笔记。 前言:只能说,在目前我所打的CTF-reverse,这类题目,第一印象就是它啦。 考查:对混淆代码的识别、反反调试的手段。 下载 查壳。 32ida打开。 还是先用动调的方式去执行。 会发现 程序直接闪退。 切换到汇编窗…

【编译原理】词法分析(编译器、转移图、正则表达式)

#词法分析 目录 编译器的阶段前端 转移图标识符的转移图关键字表算法正则表达式自动生成什么是正则表达式语法糖有限状态自动机(FA)小结 编译器的阶段 源程序→前端→中间表示→后端→目标程序 前端 其中词法分析器的作用: 字符流到单词流…

【CanMV K230 AI视觉】 人体关键点检测

【CanMV K230 AI视觉】 人体关键点检测 人体关键点检测 动态测试效果可以去下面网站自己看。 B站视频链接:已做成合集 抖音链接:已做成合集 人体关键点检测 人体关键点检测是指标注出人体关节等关键信息,分析人体姿态、运动轨迹、动作角度等…

Vue常见面试题目

computed与watch区别 computed(计算属性)watch(侦听器)定义与用途计算属性(computed)用于声明式地描述一些依赖响应式属性的计算值。当依赖的响应式属性值发生变化时,计算属性会重新求值。侦听…

【深度学习】Pytorch基础

目录 梯度下降算法(Gradient Descent)代码实现 梯度下降算法(Gradient Descent) 梯度下降算法在机器学习中应用十分的广泛,不论是在线性回归还是Logistic回归中,它的主要目的是通过迭代找到目标函数的最小…

[网络]TCP/IP协议 之 网络层IP协议(3)

文章目录 网络层IP协议NAT机制 网络层 网络层主要做的事情: 1.路径规划(路由器选择) 2.地址管理 IP协议 1)4位版本 指定IP协议的版本, 4 > ipv4 , 6 > ipv6 2)4位首部长度 4位bit能表示0-15, 单位也是4字节, 所以IP报头最长60字节, 最短20字节 3)8位服务类型(TOS) ty…

【Qt】Qt界面美化 | 绘画

文章目录 绘画概述绘制API1. 图形(1). 线段(2). 矩形(3). 圆形(4). 绘制文本 2. 工具(1). 画笔(2). 画刷 3. 绘制图片QPainter图片操作 绘图设备(1). QPixmap(2). QImage(3). QPicture 结束语 绘画概述 虽然 Qt 已经内置了很多的控件,但还是有很多时候需要“自定义…

源于AI绘画的爆火,尝试做了一个工具网站

这两天做了一个 网页 Demo,实现了一些 AI 图像处理功能,前端用的是 React,后端用的是 Django 现在 ,Demo 中已经实现的功能有两个: 1,人像分割:从图像中把人物分割出来,用一个透明…

Vue与React的Diff算法

虚拟DOM 定义 虚拟DOM是一种用于在前端开发中模拟真实DOM的技术。它是一种抽象的数据结构(简单来说就是一个Javascript对象),用于描述HTML或XML文档的结构和内容。通过将页面的状态和结构保存在内存中,而不是直接操作真实的DOM&am…

C++·io流

本节主要是了解为主,需要具体使用时可以查看文档。 io流操作指的是对各种流的操作,我们经常使用的cin和cout是对标准流的操作,实际上它还可以对文件流操作。 官网资料:Input/Output - C Reference 流输入和流提取功能的实现中有着…

鸿蒙交互事件开发04——手势事件

1 概 述 手势事件是移动应用开发中最常见的事件之一,鸿蒙提供了一些方法来绑定手势事件。通过给各个组件绑定不同的手势事件,并设计事件的响应方式,当手势识别成功时,ArkUI框架将通过事件回调通知组件手势识别的结果。 …

记录一款人气领先的开源国产 ERP 系统

推荐一款人气领先的国产ERP系统,目前在Gitee上有12.3k star,在github上面也有1.2k 管伊佳ERP(原名华夏ERP)基于SpringBoot框架和SaaS模式,立志为中小企业提供开源好用的ERP软件,目前仅支持进销存财务生产功…

2025年第八届计算机图形和虚拟国际会议(ICCGV 2025)即将召开!

2025年第八届计算机图形和虚拟国际会议(ICCGV 2025)将于2025年2月21-23日在中国成都举行。随着信息技术的飞速发展,计算机图形学与虚拟现实技术正以前所未有的速度重塑着我们的认知世界与交互体验。从沉浸式游戏到精准医疗模拟,从…

气压测试实验(用IIC)

I2C: 如果没有I2c这类总线,连接方法可能会如下图: 单片机所有的通讯协议,无非是建立在引脚(高低电平的变换高低电平持续的时间)这二者的组合上,i2c 多了一个clock线,负责为数据传输打节拍。 (i2…

Unity3d中制作触发区域为圆形的按钮

一、常规矩形的Button制作 设置Highlighed Color为绿色。 此时当鼠标在button上方时会显示绿色: 二、圆形Button制作 在Button的Image中选择Source Image为Knob。 程序运行时,鼠标在矩形和圆形之间的区域,button还是会变成绿色。 所以&…

【时时三省】(C语言基础)指针进阶 例题5

山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省 abcdef是个常量字符串 把首地址a放在了p里面 第一个p 算的是指针变量的大小 它打印就是4或者8 第二个p1 p本来是a的地址 1就是b的地址 是地址就是打印四或者八 …

chapter14-集合——(List-LikedHashSet)——day18

目录 528-LikedHashSet介绍 529-LikedHashSet源码介绍 528-LikedHashSet课堂练习 528-LikedHashSet介绍 529-LikedHashSet源码介绍 528-LikedHashSet课堂练习

【计网】从零开始认识网络socket

优于别人,并不高贵, 真正的高贵应该是优于过去的自己。 --- 海明威 --- 从零开始认识网络socket 1 网络通信流程2 IP地址 VS MAC地址3 网络socket3.1 理解源 IP 地址和目的 IP 地址3.2 传输层的典型代表3.3 网络字节序3.4 socket编程基础 1 网络通信流…

高压直流接触器及使用注意事项

高压直流接触器及使用注意事项 1.概述2.接触器和继电器有什么区别3.节能线圈4.安装位置5.直流继电器线圈抑制6.高压继电器和接触器有哪些应用?7.线圈效率的决定因素是什么?对线圈驱动器有什么要求?8.负载极性对接触器的影响9.触点参数注意事项10.线圈供电要求1.概述 航空接…