Java开发之高并发必备篇(一)——线程基础

2023-11-18

​​提到高并发,这几年几乎是火遍编程界的网络名词了。无它,随着现在互联网的高速发展特别是电商平台类的应用快速发展,互联网服务内容也越来越丰富,用户越来越多,淘宝、天猫、京东、“拼夕夕”、抖音等几乎成为了广大群众每日必用的应用了。而在这些应用中见到的“天猫双11”、“京东618”、“商品秒杀”、“火车票抢票”往往都是短时间内产生大量的并发访问量和流量,如果不解决我们也不是没有见过天猫双11崩溃的时候!那么如何解决这种高并发问题的首要基础就是能够玩好线程,所以下面的内容我们就来学习下线程。

1.为什么要有线程?

举个简单例子,假设我们在使用百度网盘这个应用,我们想要使用百度网盘的上传和下载功能。没有线程的话那么我们的操作只能是这样的: 我们上传文件的时候就不能干别的事,需要我们上传成功之后才能下载别的东西,并且上传文件也只能一个个的上传,那将是很糟糕的一个体验。那么我们想要百度网盘即可以一边上传一边下载,并且可以多个上传多个下载这样的多任务操作应该怎么办呢?没错就是使用线程了!

现在的操作系统不管是windows也好、linux系列的也好基本上都是多用户多任务的操作系统,而多任务就是靠多线程来实现的。多任务执行也就是所谓的并发。

2.操作系统中进程和线程的概念

提到线程,我们就不得不先提下进程,往往很多人认为一个进程就是一个程序,那么是不是这么一回事呢?我们来看看进程的定义。

·进程概述

系统中能够独立运行的程序被称为一个进程。进程是CPU分配资源的最小单位;

例如:windows的进程

在这里插入图片描述

每个进程都有自己独立的一块内存空间,一个单核CPU是单进程处理,即同一时间只能处理一个进程, 但是系统可以分配给每个进程一段有限的执行 CPU 的时间(被称为 CPU 时间片),CPU 在这段时间中执行某个进程,然后下一个时间段可能又跳到另一个进程中去执行,因为CPU切换的速度太快了,远远超出了我们肉眼的识别能力,所以我们看到很多的进程似乎都是同时在运行一样。而多核CPU则可以实现同时多个进程的执行,只不过因为调度的问题可能导致一个核心可能一个时间片内调用多个进程。

·线程的概述

线程是进程中完成一个流程的执行任务。是进程中的一个执行路径,跟进程共享一个内存空间。线程是程序中运行的最小单位。

线程本身不能单独存在,需要运行在进程中。一个进程可以有多个线程(例如:一个Java程序基本上都有main主线程和GC线程(垃圾回收器)等两个以上线程),同一进程的所有线程共享本进程的资源。

3.Java中的线程实现

通过前面的介绍我们认识了线程,那么在Java中线程是如何实现的呢?在Java中线程的主要实现方式有以下三种:

·继承Thread类

·实现Runnable接口

·实现Callable接口

前两种实现方式是比较常见的方式并且类和接口也都在java.long包下,第三种Callable在java.util.concurrent包中我们在后面部分会介绍其实现以及不同,我们先来看下前面两种的实现方式。

(1)继承Thread类

首先我们看到其实Thread类也是实现了Runnable接口

在这里插入图片描述

这样我们直接创建Thread对象就可以使用了。

使用步骤:

A. 继承Thread类或者直接创建Thread对象

B. 在run方法中实现线程任务代码

C. 调用Thread的start方法启动线程

在这里插入图片描述

分析:下面的方式使用起来不需要定义类使用简单一些,适合调用次数较少的情况。另外虽然Thread类线程启动之后执行的是run方法,但是线程的启动方法是start方法!

start方法和run方法的区别:

run方法只是单纯的Thread类的一个普通方法,只不过线程启动的时候会调用而已,如果只是使用 thread.run()那么也仅仅代表我们调用了thread的run方法但是并没有开启一个新的线程,代码还是在主线程main中执行。

start方法调用表示创建了一个新的线程,线程进入准备就绪状态,当线程得到cpu时间片处理时,Java 虚拟机就会调用该线程的 run 方法并执行里面的任务代码,任务代码执行完毕则线程结束。另外start开启的新的线程是一个独立的执行任务,下面的代码无须等待线程执行完毕就可以继续执行。

使用Thread类的局限性:

Thread类实现方式虽然简单,但是因为Thread是一个类,在Java中类只能进行单继承,所以对于线程的扩展能力就差。

(2)实现Runable接口

Runnable是一个函数式接口(有@FunctionalInterface修饰并只有一个抽象方法),定义非常简单只有一个run方法,源代码如下:

在这里插入图片描述

之前我们也介绍了Thread类其实也是实现了Runable接口,其中启动线程执行任务代码的run方法其实就是Runnable接口的方法。所以我们可以通过实现Runable接口配合Thread类实现线程的扩展使用。

使用步骤:

A. 定义一个类实现Runnable接口

B. 在run方法中实现线程任务代码

C. 通过Thread(Runnable r)构造方法传入Runnable接口实例对象,并调用start方法启动线程

在这里插入图片描述

分析:

使用Runnable接口的实现,因为接口可以多实现的特点,所以Runnable接口可以被更多的类实现,扩展性比Thread要强,另外又因Runnable是作为Thread构造方法传入才创建的线程所以Runnable需要依赖与Thread类使用,并且多个Thread对象可以使用同一个Runnable实例。

Runnable的Lambda表达式的使用:

Java8提供了Lambda表达式,我们使用Lambda表达式创建Runable实现类实例的时候不需要我们定义类,变得更加方便。代码实现如下:

在这里插入图片描述

4.多线程经典案例-卖票案例

虽然开发中通过继承Thread类和实现Runnable接口都可以实现线程,但是因为继承Thread类具有局限性。而实现Runnable接口更容易扩展,并且实现Rnnnable接口的实例可以被多个Thread对象共享,这样解决一些多线程处理资源就更方便一些。我们以卖票的案例来说明:

我们有三个窗口在卖票,总共有100张票,那我们怎么实现3个窗口同时都在卖,并且卖掉100张票呢?

(1)Thread类的实现

在这里插入图片描述

运行的结果:

在这里插入图片描述

结论:

最后发现每一个窗口都是卖100张票,总共卖了300张票,但是一共只有100张票,显然继承Thread类实现不方便,因为t1、t2、t3三个窗口线程不能共享100张票这个资源,所以导致都各自卖了100张。

Runnable接口的实现

在这里插入图片描述

运行的结果:

在这里插入图片描述

结论:

我们发现使用Runnable接口的方式可以让t1、t2、t3三个窗口线程同时在卖100张票,而不是每个线程都卖100张,这是因为t1、t2、t3都使用了同一个Runnable实例。显然Runnable接口的实现可以实现100张票资源的共享,但是通过运行结果我们会发现一个令人困惑的问题,就是不管程序运行多少次,总是有两个或者三个线程卖了同一张票!这是什么原因导致的呢?其实这就是所谓的著名的“多线程并发访问不安全的问题”!后面的篇章中我们会介绍为什么多线程访问对象会不安全。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java开发之高并发必备篇(一)——线程基础 的相关文章

随机推荐

  • 教你如何将磁盘中黑色的未分配空间变成绿色的可用空间

    在黑色的未分配空间上建立新的卷 使用分区助手或者DiskGenius将新建立的卷从主分区转换成逻辑分区 在磁盘管理中删除这个卷 然后就会变成绿色的空用空间
  • MySQL 体系结构

    一 物理文件 参数文件 告诉Mysql实例启动时在哪里可以找到数据库文件 并且指定某些初始化参数 这些参数定义了某种内存结构的大小等设置 用文件存储 可编辑 若启动时加载不到则不能成功启动 与其他数据库不同 参数有动态和静态之分 静态相当于
  • java面向对象 继承 && 多态

    目录 继承性 inheritance 为什么要有继承 作用 继承举例 方法的重写 重写举例 四种访问权限修饰符 关键字 super 关键字super举例 调用父类的构造器 调用父类构造器举例 子类对象的实例化过程 多态性 概念 使用 多态性
  • vue弹出遮罩层弹窗后禁止底部页面滑动

    方法一 在遮罩层标签上添加 touchmove prevent 方法二 遮罩层显示时把下方的父盒子css设置为固定定位宽100 高100vh 超出隐藏 content width 100 height 100vh overflow hidd
  • Kali Linux介绍(安装教程)

    一 Kali Linux是什么 Kali Linux是基于Debian的Linux发行版 设计用于数字取证操作系统 每一季度更新一次 由Offensive Security Ltd维护和资助 最先由Offensive Security的Ma
  • 以太坊2.0-上海升级节点详细搭建文档

    文章目录 一 配置 JWT 认证 二 部署执行节点geth 2 1 下载geth二进制文件 2 2 geth节点启动 三 部署共识节点Prysm 3 1 下载Prysm脚本 3 2 Prysm容器生成 四 检查节点是否同步完成 4 1 检查
  • 第二十五节:动态和静态合集

    DOM是JavaScript重要组成部分 在DOM中有三个特别的集合分别是 NodeList 节点的集合 NamedNodeMap 元素属性的集合 和HTMLCollection html元素的集合 这三个集合有一些共同的特点 它们都是一个
  • cannot import name filters

    源代码报错如下 from skimage import color filters ImportError cannot import name filters 在命令行输入 conda list 查看scikit image的版本号 我的
  • Flex 布局全解

    一 Flex布局是什么 Flex是Flexible Box的缩写 意为 弹性布局 用来为盒状模型提供最大的灵活性 任何一个容器都可以指定为Flex布局 box display flex 行内元素也可以使用Flex布局 box display
  • 关于6轴传感器LSM6DSLTR的调试说明

    关于6轴传感器LSM6DSLTR的调试说明 AP的检测脚需要配置为pull down的 不能配置为pull up 否则中断脚一直是高 sensor的int1脚配置为open drain模式 可以配置wakeup中断 阈值设置为1 2g产生中
  • IT项目管理之第6章 项目成本管理习题选择题汇总

    IT项目管理之第6章 项目成本管理习题选择题汇总 第6章项目成本管理习题选择题汇总 叮嘟 这里是小啊呜的学习课程资料整理 好记性不如烂笔头 今天也是努力进步的一天 一起加油进阶吧 第6章项目成本管理习题选择题汇总 1 一个组织正在考虑一个项
  • SQL Server: Get table primary key and Foreign Key using sql query

    所有用户表 主键 外键 描述等信息 涂聚文 20150924 Geovin Du SELECT tbl name AS TableName clmns name AS ColumnName usrt name AS DataType ISN
  • csv文件中出现乱码的解决方法

    1 首先用UE打开CSV文件 发现没有乱码了 2 然后新建一个txt文本 把CSV中的数据复制到txt文本中 保存格式为ANSI ASCII 3 复制txt文件 再把副本后缀改为CSV格式 再用EXCEL重新打开就没有乱码了 csv文件中有
  • 整合Druid数据源(springboot学习笔记10)

    1 导入Druid依赖 这个依赖有普通的 也有springboot专属的启动器类型 两者都一样 版本也是同时更新的 普通版
  • 排序之冒泡 选择 插入 快速(c++)

    by Nicole 11 2017 include
  • Vue项目打包详细过程(非nginx代理配置)

    Vue项目打包部署至阿里云ECS 将项目入口文件中含有跨域连接的地址改为服务器地址 将Config目录下index js中的build中的assetsPublicPath修改为 在build目录下util js中添加publicPath 同
  • docker安装openwrt

    docker安装openwrt docker安装openwrt 安装问题 1 docker Error response from daemon failed to create the macvlan port devic 插件安装 do
  • [Basic]测试的概念 - 集成测试- 系统测试- 验收测试- 回归测试 -

    b 集成测试 英文是Integration Testing b 集成测试是指一个应用系统的各个部件的联合测试 以决定他们能否在一起共同工作并没有冲突 部件可以是代码块 独立的应用 网络上的客户端或服务器端程序 这种类型的测试尤其与客户服务器
  • Mpvue介绍

    Mpvue是什么 Mpvue是一个基于Vue的微信小程序前端框架 可以让我们用vue的语法写小程序的项目 简单来说就是 以前我们写微信小程序 必须借助微信小程序的开发者工具 微信开发工具提供的语法才能写小程序 Mpvue的出现 让我们可以先
  • Java开发之高并发必备篇(一)——线程基础

    提到高并发 这几年几乎是火遍编程界的网络名词了 无它 随着现在互联网的高速发展特别是电商平台类的应用快速发展 互联网服务内容也越来越丰富 用户越来越多 淘宝 天猫 京东 拼夕夕 抖音等几乎成为了广大群众每日必用的应用了 而在这些应用中见到的