多线程之基础篇(一)

一、Thread类

1、线程的创建 

大家都熟知创建单个线程的三种方式,通过继承Thread类创建线程并重写该类的run()方法;通过实现Runnable接口创建线程一样要重写run()方法;以上的两个run()方法都是线程的执行体;第三,使用Callable和Future来创建线程Callable接口提供了一个call()方法来作为线程的执行体,call()方法比run()方法功能要更加强大,call()方法可以有返回值,call()方法可以声明抛出异常(前两种如果要抛异常只能通过try,catch来实现);下面详细介绍一下Callable和Future

我们知道创建线程最终要由操作系统支持,java中只有调掉Thread对象,最后执行一个叫private native void start0();的本地方法,而该方法的最终实现在C++和C层面,要阅读JVM源码才能更深一步,暂时咱们知道最后是由操作系统给我们另起了一个线程取执行 “执行体”里面的业务。我们看Thread类的构造方法里面没有直接传Callable接口的构造方法,那为啥我们还能运行下面这段代码呢?

    /*** Callable需要配合FutureTask使用* FutureTask的get()可以返回任务的执行结果,方便在2个线程之间,把一个线程的结果传给另一个线程** @throws InterruptedException* @throws ExecutionException*/private static void testFutureAndCallable() throws InterruptedException, ExecutionException {FutureTask<Integer> future = new FutureTask<>(() -> {log.debug("running.....");Thread.sleep(1000);return 100;});Thread t3 = new Thread(future, "t3");t3.start();// 当主线程运行到get方法时,主线程会阻塞住,一直等待 t1线程 结果返回log.debug("main接收future的返回值:{}",future.get());log.debug("main线程继续运行....");}

我们可以看到,直接把future对象传入给了Thread构造方法,其实我们可以从FureTask出发, FutureTask实现了RunnableFuture接口,而RunnableFuture又同时实现了Runnable和Future接口,所以在直接构造Thread时可以直接传入构造参数执行。

public class FutureTask<V> implements RunnableFuture<V> {}public interface RunnableFuture<V> extends Runnable, Future<V> {}

尽管FureTask+Callable有返回值,可以抛异常,可以查看线程执行任务的情况,但是有时候为获取它的返回值主线程而陷入阻塞等待,另一个isDone()方法轮询获取值容易耗CPU资源.........

针对以上2个痛点JDK做了扩展CompletableFuture类同时实现了Future和CompletionStage接口,在CompletionStage上做了极大的扩展

Runnable——没有输入参数,也没有返回值

Function——功能型函数接口,有一个参数,有一个返回参数

Consumer——消费型函数接口,有一个输入参数,没有返回参数

—Consumer延申BiConsumer,有两个输入参数,没有返回参数

Supplier——供给型函数接口,没有输入参数,有返回值

数式接口名称方法名称参数返回值
Runnablerun无参数无返回值
Functionapply1个参数有返回值
Consumeraccept1个参数无返回值
Supplierget无参数有返回值
BiConsumeraccept2个参数

无返回值

2、interrupt()、interrupted()、isinterrupted()  

public void interrupt()

实例方法

,Just to set the interrupt flag

实例方法interrupt()仅仅是设置线程的中断状态为true,发起一个协商而不会立刻停止线程。

如果线程处于被阻塞状态(例如处于sleep,wait,join等状态),在别的线程中调用当前线程对象的interrupt方法,那么线程将立即退出被阻塞状态,并抛出一个InterruptException异常。

public static boolean interrupted()

静态方法,Thread.interrupted();

判断线程是否被中断并清除当前中断状态。

这个方法做了两件事

1.返回到当前线程的中断状态,测试当前线程是否已被中断。

2.将当前线程的中断状态清零并重新设为false,清除线程的中断状态

public boolean isInterrupted()

实例方法

判断当前线程是否被中断(通过检查中断标志位)

二、Java的锁  

乐观锁:

        1、版本号version

        2、CAS(compareAndSwap)算法,java原子类(Atomic打头的类)中的递增操作就是通过CAS自旋实现的。——Unsafe类

使用场景:适合读操作多的场景,不加锁的特点能够使其读取操作的性能大幅提升。乐观锁则直接去操作同步资源,是一种无锁算法

悲观锁: 同一时间点有且仅有一个线程占有锁

        1、synchronized

        2、ReentrantLock

使用场景:适合写操作多的场景,先加锁可以保证写操作时数据正确,现实的锁定之后在操作同步资源 

1、synchronized

 为什么任何一个对象都可以成为一把锁?

因为Java中所有的对象都默认继承了超类Object,而Object在JVM源码(C++)层面关联了一个对象ObjectMonitor,所以每个对象“天生”都带着一个对象监视器,也就是每一个被锁住的对象都会和Monitor关联起来。

 ObjectMonitor中有几个关键属性

_owner指向持有ObjectMonitor对象的线程
_WaitSet存放于wait状态的线程队列
_EntryList存放处于等待锁block状态的线程队列
_recursious锁的重入次数
_count用来记录该线程获取锁的次数

管程:Monitors,也叫监视器

是一种程序结构,结构内的多个子程序(对象或模块)形成的多个工作线程互斥访问共享资源。这些共享资源一般是硬件设备或一群变量。对共享变量能够进行的所有操作集中在一个模块中。(把信号量及其操作原语“封装”在一个对象内部)管程实现了在一个时间点,最多只有一个线程在执行管程的某个子程序。管程提供了一种机制,管程可以看作一个软件模块,它是将共享的变量和对于这些共享变量的操作封装起来,形成一个具有一定接口的功能模块,进程可以调用管程来实现进程级别的并发控制。

注:synchronized和 static synchronized前者是对象锁,后者是类锁,属于不同的锁,a线程加对象锁,b线程加类锁,加锁不同,a、b线程不会产生竟态条件。

 2、自旋锁

没有成员变量的类一般都是线程安全的

cynchronized

 

 

并发压测工具 

 

 装饰器模式:Collections以synchronized打头的的实现集合的那些方法就是采用了装饰器模式。

1、AQS

AQS全称是AbstractQueuedSynchronizer,是阻塞式锁和相关的同步器工具的框架

特点:

1、用state属性来表示资源的状态(分独占模式和共享模式),子类需要定义如何维护这个状态,控制如何获取锁和释放锁

—getState-获取state状态

—setState-设置state状态

—compareAndSetState-cas机制设置state状态[compare式保证state的原子性]

2、提供了基于FIFO的等待队列,类似于Monitor的EntryList

3、条件变量来实现等待、唤醒机制,支持多个条件变量,类似于Montor的WaitSet

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构】前言概况 - 树

&#x1f6a9;纸上得来终觉浅&#xff0c; 绝知此事要躬行。 &#x1f31f;主页&#xff1a;June-Frost &#x1f680;专栏&#xff1a;数据结构 &#x1f525;该文章针对树形结构作出前言&#xff0c;以保证可以对树初步认知。 目录&#xff1a; &#x1f30d;前言:&#x1f3…

极光笔记 | 推送服务数据中心选择:合规性与传输效率的双重考量

随着全球化进程的深入&#xff0c;跨境数据传输与存储问题已经变得愈发重要。推送服务的数据中心节点选择不仅关乎数据访问速度和用户体验&#xff0c;同时也直接牵扯到数据合规性和安全保障。EngageLab Push深知这一点&#xff0c;为了满足更多国际客户和全球用户触达需求&…

将本地jar包手动添加到Maven仓库依赖处理

一、起因 在日常开发中&#xff0c;经常会遇到一些情况&#xff0c;就是在更新Maven时&#xff0c;从网上下载jar包的时候网络不稳定或者其他原因导致jar包数据缺失而导致的依赖无法正常引入的情况. 还有一些其他情况如个人jar包一类的。 二、解决 以前以上这些情况&#x…

Android12之/proc/pid/status参数含义(一百六十五)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

微服务·数据一致-seata

微服务数据一致-seata 概述 Seata&#xff08;Simple Extensible Autonomous Transaction Architecture&#xff09;是一个开源的分布式事务解决方案&#xff0c;旨在帮助应用程序分布式事务管理的挑战。Seata提供了一套全面的工具和框架&#xff0c;可用于实现跨多个数据库和…

网络安全之认识网络安全网格架构(CSMA)

“网络安全网格&#xff08;CyberSecurity Mesh&#xff09;”是 Gartner 提出的网络安全技术发展新趋势&#xff0c;近两年连续入选其年度重要战略技术趋势研究报告&#xff0c;成为当前网络安全领域流行的热词&#xff0c;受到网络安全从业者的高度关注。 一、概念产生的背景…

软件测试/测试开发丨Web自动化 PageObject设计模式

点此获取更多相关资料 本文为霍格沃兹测试开发学社学员学习笔记分享 原文链接&#xff1a;https://ceshiren.com/t/topic/27167 一、page object 模式简介 马丁福勒个人博客 selenium 官网 1.1、传统 UI 自动化的问题 无法适应 UI 频繁变化无法清晰表达业务用例场景大量的样…

python 学习笔记(5)——SMTP 使用QQ邮箱发送邮件

目录 发送邮件 1、准备工作&#xff1a; 2、发送纯文本信息内容&#xff1a; 3、发送 HTML 格式的内容&#xff1a; 4、发送带附件的邮件&#xff1a; 5、群发&#xff08;一个邮件&#xff0c;发给多个人&#xff09;&#xff1a; 发送邮件 以下都 以 QQ邮箱 为发送方举…

Nginx+Tomcat(多实例)实现动静分离和负载均衡

一、Tomcat 多实例部署 1.在安装好jdk环境后&#xff0c;添加两例tomcat服务 #解压安装包 cd /opt tar zxvf apache-tomcat-9.0.16.tar.gz#移动并复制一例 mkdir /usr/local/tomcat mv apache-tomcat-9.0.16 /usr/local/tomcat/tomcat1 cp -a /usr/local/tomcat/tomcat1 /usr…

记录一次开机内存分析的全过程

作者&#xff1a;zzy的学习笔记 记录一次开机内存分析的全过程&#xff0c;尽量详尽的介绍常用内存分析工具和命令行的使用&#xff0c;结合具体问题探讨开机内存分析的实践经验。通过这篇文章我会介绍开机内存的常用测试分析工具的基本使用方法&#xff0c;以及如何通过抓取出…

在Ubuntu上建立博客网站,利用Cpolar+Inis快速实现专业写作

文章目录 前言1. Inis博客网站搭建1.1. Inis博客网站下载和安装1.2 Inis博客网站测试1.3 cpolar的安装和注册 2. 本地网页发布2.1 Cpolar临时数据隧道2.2 Cpolar稳定隧道&#xff08;云端设置&#xff09;2.3.Cpolar稳定隧道&#xff08;本地设置&#xff09; 3. 公网访问测试总…

springboot+redis

1.pom.xml <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency> 2.yml配置 # redis 配置redis:host: 127.0.0.1#超时连接timeout: 1000msjedis:pool:#最大连…

盲打键盘的正确指法指南

简介 很多打字初学者&#xff0c;并不了解打字的正确指法规范&#xff0c;很容易出现只用两根手指交替按压键盘的“二指禅”情况。虽然这样也能实现打字&#xff0c;但是效率极低。本文将简单介绍盲打键盘的正确指法&#xff0c;以便大家在后续的学习和工作中能够提高工作效率…

Pytorch Advanced(三) Neural Style Transfer

神经风格迁移在之前的博客中已经用keras实现过了&#xff0c;比较复杂&#xff0c;keras版本。 这里用pytorch重新实现一次&#xff0c;原理图如下&#xff1a; from __future__ import division from torchvision import models from torchvision import transforms from PIL…

2024年java面试--mysql(2)

系列文章目录 2024年java面试&#xff08;一&#xff09;–spring篇2024年java面试&#xff08;二&#xff09;–spring篇2024年java面试&#xff08;三&#xff09;–spring篇2024年java面试&#xff08;四&#xff09;–spring篇2024年java面试–集合篇2024年java面试–redi…

FPGA实战小项目3

基于FPGA的波形发生器 基于FPGA的波形发生器 基于FPGA的beep音乐播放器设计 基于FPGA的beep音乐播放器设计 基于FPGA的cordic算法实现DDS sin和cosine波形的产生 基于FPGA的cordic算法实现DDS sin和cosine波形的产生

iframe 实现跨域,两页面之间的通信

一、 背景 一个项目为vue2&#xff0c;一个项目为vue3&#xff0c;两个不同的项目实现iframe嵌入&#xff0c;并实现通信 二、方案 iframe跨域时&#xff0c;iframe组件之间常用的通信&#xff0c;主要是H5的possmessage方法 三、案例代码 父页面-vue2&#xff08;端口号为…

JWT 使用教程 授权 认证

JWT 1.什么是JWT JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally s…

轻松搭建本地知识库的ChatGLM2-6B

近期发现了一个项目&#xff0c;它的前身是ChatGLM&#xff0c;在我之前的博客中有关于ChatGLM的部署过程&#xff0c;本项目在前者基础上进行了优化&#xff0c;可以基于当前主流的LLM模型和庞大的知识库&#xff0c;实现本地部署自己的ChatGPT&#xff0c;并可结合自己的知识…

Zabbix登录绕过漏洞复现(CVE-2022-23131)

0x00 前言 最近在复现zabbix的漏洞&#xff08;CVE-2022-23131&#xff09;&#xff0c;偶然间拿到了国外某公司zabbix服务器。Zabbix Sia Zabbix是拉脱维亚Zabbix SIA&#xff08;Zabbix Sia&#xff09;公司的一套开源的监控系统。该系统支持网络监控、服务器监控、云监控和…