多线程从认识到理解到使用(Java)

Java——关于实现多线程的测试小题,帮助我们更好的理解多线程的使用方法 前面讲解了关于多线程的使用方法,这篇文章则是进行实战,做几道测试题。感兴趣的情况下可以看一下。 阅读详情

多线程这个章节还是有点东西的,但是你放心,我都会举一些好玩的例子,让你在不知不觉中就看懂了。

什么是进程

定义,我知道你们不喜欢看。所以来看看我的例子。

假如你是一个牛马(不要玻璃心哦),你在一个公司上班,你的老板就会发任务给你做,而你肯定还有同事,你干你的事,你同事干他的事,你们互不搭理(不熟啊)。而我们就可以看为,你就是一个进程,你完成你自己的事(进程执行自己的代码),你同事完成他的事(多个进程之间“同时”执行“多个代码),你们互不搭理(多个进程之间不会干扰,也就是假如你不干了,但是你同事还是一样干(一个进程崩了,别的进程还是可以工作的)),这个是好事,你总不会认为公司少了你的干不了吧(个别原因除外),而老板发任务给你们就是(操作系统下发任务给进程)。

线程

还是上面的故事,我们接着往下说,假如你变为了老板,你的主要任务是什么,赚钱(对,你不要说俗,老师都是为了钱)那你想赚钱,你可以想什么办法呢,两方面,一个是找更多业务(这个要考虑的东西就多了,所以不是首选)二就是让一个员工做更多的事(资本是这样的),我们业务数就这么多,一个人做多了,就可以裁员,也就省下了钱。所以在计算机中也是这样,一个进程,他做事做少了。我们就想要提高他的效率(我们就想他做更多的事),所以我们就发明了线程,一个进程可以有多个线程,但是最少一个线程。(就是你可以同时做几个项目,但是你最少要一个,因为你一个都不做,那裁员不裁你裁谁)

总结一下,进程就是相当于一个员工完成全部的工作,而线程就是员工完成具体的一件事。

进程和线程的区别

因为线程就是员工完成具体的一件事,而进程是员工完成全部的工作,所以进程的体量要比线程大的多,所以下面就好理解了。

创建线程⽐创建进程更快

 销毁线程⽐销毁进程更快

 调度线程⽐调度进程更快。

还要一个最主要的区别就是,不同的进程是有不同的内存空间的,而在同一个进程下的多个线程他们是公用一个内存空间的。这个非常好理解,因为进程就是相当于一个员工要完成的工作,而我们每一个员工都有自己的工作岗位吧(应该不会有没有岗位的吧),而线程是一个员工要完成具体的一件事,所以多线程就是一个员工要干好多事,那还不是这个员工干啊,这个员工也还是这个岗位啊。

后面一些线程的使用,就是自己看看文档,看看资料就会的,没有什么要理解的,我就不写了。,我们后面写的基本就是两个一个start(线程开始)join(等待线程结束)所以我们接下来聊一聊线程的重量级(线程安全)

线程安全

线程随机调度问题

我们想要一个线程安全,就要知道他为什么不安全,而不安全的原因就是线程调度的随机的,给大家讲一个最痛苦的经历,就是你小时候打游戏,突然你妈不让你打了,让你去吃饭,这个就是线程调度,所以说线程调度是很痛苦的,我们从一个问题出发。

public static int count = 0;
    public static void main(String[] args){
        Thread thread = new Thread(()->{
            for(int i = 0;i<5000;i++){
                count++;
            }
        });
        Thread thread1 = new Thread(()->{
            for(int j = 0;j<5000;j++){
                count++;
            }
        });
        thread.start();
        thread1.start();
        try {
            thread.join();
            thread1.join();
        }catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(+count);
    }

这个就是典型的我们创建两个线程,同时加一个数,大家觉得这个打印出来的数是多少。10000?如果你说10000

嘻嘻,我还真的就搞出来了10000,但是还是错了,(™的,我第一次调试的时候,还真的是10000,搞的我还以为写错了,后面就正常了)

是一个随机的数,那为什么是一个随机的数呢,这个就是因为线程调度了。看下面

计算机在做count++的操作的时候,分为了三步,1.拿到count的值。2.把这个值++,3.把新的值放回原来的位子。而计算机为什么要分为三步呢(我也想一步搞好,条件不允许啊)。而这个又是线程,而线程调度就把这个东西打乱了,看图

因为在t1调度的时候,我们只拿到了count = 900,就被调度去执行t2,t2还是拿count = 900,这样我们要执行两次的++,就只执行了1次。那我问你,

这个值是不是一直都是5000以上呢,你说对啊,tall me why

你说这个不就是两个可能一个是两个没有穿插,就是都成功了,还有就是两个穿插,只成功一个。那我们要最小的不就是,全部都穿插,都只成功一个,不就是5000吗,一点聪明,但是我的评价是一般(虽然一开始我也是这样想的)那你想,假如

兄弟们,虽然这个情况特别极端,那我问你,会不会发生,所以这个数是可以小于5000的,只不过特别极端。但是一个服务器这么多人,使用这么多次,就可能会触发很多次,不过这个是后话,因为就上面一个随机数,可能老板就要骂你了。所以下面我们就说说解决方法,

线程随机调度的解决方法

其实看了我上一篇MySQL的索引和事务(事务的隔离一看就懂)-优快云博客的小伙伴已经知道了,在聊事务的时候,事务有一个特性叫原子性,就是做一个事,要不全部成功,要不全部失败。所以我们就需要让count++这样的操作有原子性,所以这个时候我们就需要使用到synchronized这样的关键字,所以我们就来看看synchronized是怎么使用的

locket这个是锁的类型,等下聊,后面的大括号就是进去加锁,出来就解锁,而我们为什么要这样设计呢,就是为了怕我们会忘记解锁,你说这个不是基本操作吗,写出这个bug不是程序员的问题吗,确实,在我们这个情况下确实不会忘记,但是假如有锁的情况下报错了,出异常了,就很容易忘记,虽然这个确实是我们失误,但是我们还是可以通过别的方法来避免这样的失误,

现在聊聊locket这个锁的类型,这个就是我们随便拿一个类型创建的一个变量,我们也可以创建几个变量为不同的锁,我想到一个特别的例子,就是上厕所,locket就是厕所门(有锁的),我在里面的时候(上了锁),你是不是就进不来了,就有人说,为什么我一定要去你那个厕所,我不能换一个吗。你当然可以换一个,而且你还可以成功的进去(别的厕所没有上锁),但是我写的代码命令你一定要上locket的厕所,所以你只能在外面等我,你想想外面的count++,加了锁,两个线程就不可以穿插了,就不会发生count的数是随机的了,(我们把这个叫为线程安全)。

可见性问题和解决方法

我们还是先看一个问题

我先讲讲,我这个题的思路啊,我们先创建一个变量,我们在thread里面让他一直循环,一直到我们的flag不为0的时候,就打印循环结束。而我们只有在thread1中,我们随便输入一个数,flag才不会为0,所以我们看执行结果。

我大概等了1分钟还是没有出来,这个就是thread还在循环,他没有停下来,但是我们明明有一步把他变了啊,这个就是典型的内存可见性问题了。首先,我们看看官方解释吧

讲简单就是这个程序有一个内存空间(这个就是那个硬件的内存),而我们单独为线程开辟了内存空间(这个实际上就是cpu的寄存器)而计算机为什么要单独开辟空间啊,直接用内存不就好了啊,这个其实就是寄存器和内存的区别了(能不能想起来),主要的就三点,一。内存的存储空间大,寄存器小。二。寄存器访问速度快,内存慢。三。内存断电内容可以保存。但是和这个相关的就是第二点寄存器访问速度快,可以提高效率,那我问你

寄存器效率搞高,为什么要内存

孩子们,寄存器贵啊,就像谁不想天天吃好的,喝好的啊,没钱啊。

我们有点说远了,但是还是和这个题有关的。来我们上面聊到了,分为主内存和工作内存,程序的叫主内存,单一线程的叫工作内存,我们在执行线程的时候,我们会把主内存的变量拷贝到工作内存上面,但是计算机拷贝了几次发现都是这个数,后面就懒的拷贝了(jvm的效率优化功能),所以才会出现,我在thread1里面修改了数,但是thread里面就没有改。这个解决方法很简单,就是给这个变量加volatile(这个就是告诉计算机,这个数后面要改,你不要偷奸耍滑),就可以正常实现了。

可重入问题和解决方法

可重入问题,其实就是字面意思,就是一个锁对自己再锁一次,有没有成为死锁。

就是相对于这样,我和大家解释一下这个代码啊,首先我们进入第一个synchronized,就从写加锁的地方开始,但是我在下一个的代码中我第二个synchronized要加锁,,而我要拿到这个锁是不是就要释放第一个synchronized,是不是就要走到第一个synchronized结锁的地方,但是我都卡在了第二个加锁的地方,我怎么走到第一个锁结锁的地方呢,这个就是死锁,但是这个的解决方法,很简单,因为synchronized就是可重入锁,这种就可以编译过

死锁还有一种情况,是这样一个场景,我和你两个人吃牛排,吃牛排不是一般要刀和叉子吗(假设少一个都吃不了),我手上有一把刀,你手上有一把叉子,我们两个都想先吃,所以我找你要叉子,你又找我要刀,就卡在这里了,这个也是一种死锁,就有两个线程,一个线程各有一把锁,但是完成任务要两把锁才可以做,所以就卡了。这个是解决方法也很简单,就比如我们两吃牛排,我们分一个主次就好了,这个线程也分一个谁先谁后就好了。

这个线程安全还是有点意思的,希望对大家有帮助,这个是我写的下一篇,使用今天的多线程来写一个可以使用的程序,来对今天的多线程学习做一个反馈。 多线程2(定时器的实现)-优快云博客

Matlab子图排版终极指南:从tight_subplot到tiledlayout的实战对比 本文深入对比Matlab中两大子图排版工具:社区经典函数tight_subplot与官方现代布局管理器tiledlayout。针对默认subplot产生的子图间距与边缘距离问题,详细解析两者的设计哲学、参数控制与实战应用,帮助用户根据版本与需求选择最佳方案,实现高效、精确且美观的多子图排版。 阅读详情

相关推荐

ArcGIS 泛克里金插值

按照如图所示的步骤填写参数,1处选择subset features。 2:输入数据。 3:输出训练数据。 4:输出测试数据。 5:80,表示80%的比例是训练数据,20%是测试数据。 6:输入的百分比。 1:选择geostatistical wizard。 2:插值方法,克里金插值 3:训练数据。 4:数据字段。 点击下一步: 1:表示泛克里金插值。 2:输出表面类型。 3:转换类型none。 4:趋势剔除的阶数。 点击下一步: 表示东北—西南方向变化平缓。 1:模型优化 2:模型类型(stabl.

yuanYW7556的博客 7275

java多线程初步认识到更深的理解

多线程得学会,面试必问,工作中也能解决很多开发问题

再见天涯 248

保姆级教程:手把手教你从ENSEMBL官网下载GRCh38/GRCh37的GTF注释文件(附网址规律总结)

本文提供从ENSEMBL官网下载GRCh38/GRCh37的GTF注释文件的详细教程,包括路径解析、版本号确定和下载命令示例。特别解析了GRCh37的特殊存储结构,并分享批量下载、文件校验等高级技巧,帮助生物信息学研究者高效获取基因组注释文件。

weixin_29289821的博客 204

java多线程详细理解

明确一点:多线程不是为了提高程序执行速度(性能甚至更低),而是提高应用程序的使用效率。 多线程的三大特性:原子性、可见性、有序性 一、创建线程 创建线程额的开销:分配内存 --> 列入调度 --> 线程切换的时候还要执行内存换页,CPU 的缓存被清空,切换回来的时候还要重新从内存中读取信息(破坏了数据的局部性) 创建线程的三种方式: 1.继承Thread(重点),重写run()方法,在main函数中,调用start()方法 2.实现Runnable接口(重点),重写run()方法,在main函数

YangGuang的博客 8901

基于Simulink的魔术公式轮胎动力学仿真

本篇博文主要用来记录汽车系统动力学课程的学习,仅供课程阶段参考,与实际工程应用还有较大距离。基于Simulink的魔术公式轮胎动力学仿真本实例主要有以下任务。1.建立魔术公式轮胎动力学仿真模型。2.绘制不同载荷下的轮胎纵向力—滑动率关系曲线。3.绘制不同载荷下的轮胎侧向力—侧偏角关系曲线。4.绘制不同载荷下的轮胎回正力矩—侧偏角关系曲线。提示:以下是本篇文章正文内容,下面案例可供参考。

shy_201992的博客 6940

【2025最新版】间接平差——以水准网平差为例 (python详细过程版)

水准网间接平差的python代码实现。博客长期更新,本文最新更新时间为:2025年5月20日。

点云侠的博客 1702

Java多线程的使用,一篇文章带你理解多线程,手把手的代码实现案例

Java基础知识多线程的使用(重点知识),一篇文章带你理解多线程,全文干货,收藏起来慢慢看,相信会有不少收获~~~

青春无问西东 岁月自成芳华 2735

L3自动驾驶时代,域控制器核心解析(第一篇:架构演进与五域基础)

本文作为L3域控制器系列的第一篇,核心梳理了3个关键内容:L3时代为什么必须用域控制器:解决分布式ECU的协同、算力、迭代难题;域控制器的演进路线:从分布式ECU→域集中式→中央计算平台;博世五域架构的核心解析:五大域的定位、功能与典型方案。后续将持续更新系列文章,重点覆盖:第二篇:L3对域控制器的关键技术要求(传感器、算力、线控、软件、通信);第三篇:域控制器全产业链拆解(上游芯片、中游器件、下游总成);第四篇:域控制器的产业机遇与国产替代进展。

getusushu的博客 533

JAVA多线程理解

线程(multithreading),是指从软件或者硬件上实现多个线程并发执行的技术。多线程程序应用能够在同一时间执行多于一个任务,进而提升整体处理性能。本文将从最基础的部分开始讲解JAVA线程的知识,最后深入了解JAVA多线程的高级应用以及优化。

qq_22610595的博客 823

Oracle EBS 寄销/VMI(1)-->基础设置

名词解释:     BPA:一揽子采购协议     BPR:一揽子发放     SR:来源补充规则     ASL:合格供应商列表     VMI: 供应商管理库存     寄售(Consignment)是把货物放在客户那里,客户要用的时候才付款的库存,一般是指卖方把

陈显平的专栏-Oracle EBS 1万+

高通平台开发系列讲解(USB篇)MBIM协议详解

📢本文主要介绍高通平台USB网卡MBIM协议。

内核笔记 5438

【Java并发】多线程的入门与理解

Java并发 -- 多线程的入门与理解

2403_87459748的博客 1689

stable-diffusion-webui的逐步部署教程

本文主要介绍了stable-diffusion-webui的逐步部署教程,希望能对使用Stable Diffusion的同学们有所帮助。 文章目录 1. 前言 2. 逐步部署教程 2.1 创建Python环境 2.2 安装依赖库 2.3 运行代码

weixin_43178406的博客 6万+

Thread线程从零认识到深层理解——初识

一直对线程相关知识熟练使用但又感觉不是精深,现抽时间通过对线程的原理、基本使用、线程状态、线程中断、线程安全、线程池的详细梳理,整理成线程的系列博客文章,搭建成自己的一个线程知识体系,帮助自己更加全面深刻的认知和理解线程,希望对各位看官也能有帮助。

luo_boke的博客 2181

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

理解 Java 中的多线程编程

多线程编程是 Java 开发中的一项重要技能,能够显著提高程序的性能和响应性。本文从基础概念入手,详细讲解了 Java 中的多线程实现方式、线程同步与通信、线程池、并发集合以及死锁与活锁的避免方法,并通过实际案例加深理解。希望本文能够帮助新手朋友全面掌握 Java 多线程编程,提升开发技能。

这家伙很懒,什么都没有留下 1058

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

java多线程的理解和使用

例如:计算机CPU有2核4线程、4核8线程、8核16线程、16核32线程、32核64线程,如果任务线程数少于计算机最大线程数,那么此时就是一个计算机线程处理一个任务的线程,也就是并行;如果任务线程数大于计算机最大线程数,那么此时就是一个计算机线程处理一个或多个任务的线程,也就是并发(伪并行,让所有任务“看似同时”执行)。比如:软件中的耗时操作、所有的聊天软件、所有的服务器。多线程可拆解为“多”和“线程”,多既是多个,并发:在同一时刻,有多个指令在单个CPU上。并行:在同一时刻,有多个指令在多个CPU上。

xiudogbuxiu的博客 430

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

如何理解Java多线程?

线程和进程 进程:是一个正在执行的程序 每个进程执行都有一个执行顺序,改顺序是一个执行路径,或者叫一个控制单元 线程:就是进程中的一个独立控制单元,线程控制着进程的执行 一个进程中至少有一个线程 多线程:CPU轮流执行每个进程(我们所谓的同时启动几个APP,看上去是同时运行,其实CPU在进程之间做着高速切换) Java中的多线程 如何在自定义的代码中,自定义一个线程呢? 查找API,发现Java中...

bigestboss的博客 772

记录Java多线程理解

记录了我在学习多线程的时候的一些看法。

想看什么文章都可以私信给我,综合性博客。 924

多线程的理解

多线程的理解 什么是多线程? ​ 多线程的简单理解,即:同时处理多个事项,宏观方面可以理解为计算机在cpu的调度下,同时进行多项工作;类比可以看做,武侠高手左手画圆,右手画三角形,同时进行;但是,实际上微观理解,单核cpu同一时间只能处理一件事情,所以是将各个线程分为细小的时间片来交替进行,但是由于相对于人类感官速度极快,产生统一时间俩件事情同时进行了。打个比方,现在用一台单核cpu计算机,同时打开俩个视频,只看视频播放画面,其实是将视频切割为一个个细小的时间片交替cpu调度执行,同一时间点,只有一个在被c

qq_36098674的博客 3150

Java多线程,Future的使用与理解

Java多线程,Future的使用与理解 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。 Future模式简述 传统单线程环境下,调用函数是同步的,必须等待程序返回结果后,才可进行其他处理。 Futrue模式下,调用方式改为异步。 Futrue模式的核心在于:充分利用主函数中的等待时间,利用等待时间处理其他任务,充分利用计算机资源。 主要角色 #Main:系统启动,调用Client

weixin_44275595的博客 424

java多线程的理解

对于多线程的理解,我从已开始听的很模糊。 线程就是一个进程里多个线程执行同一个数据的不同路径,简单来说,就是多个人在一个桌上吃同一个碗里的同一种菜,不知道这样大家能看明白不,我在理解这里的代码时,有许多困难,因为毕竟没有现实场景的辅助很难理解这些概念型性的知识, 好的,废话不多说,咋直接上代码吧! 首先先给各位上一个线程的继承类,就继承Thread吧 /*首先咋先自定义类Mythread...

weixin_45770080的博客 171

Java中多线程的理解和使用

多线程的理解和使用

m0_49124752的博客 342

java中多线程理解总结

1.理解多线程首先我们要了解什么是串行、并发、并行串行:一个线程执行到底,相当于单线程。并发:多个线程交替执行,抢占cpu的时间片,但是速度很快,在外人看来就像是多个线程同时执行。并行:多个线程在不同的cpu中同时执行。并发与并行的区别:并发严格的说不是同时执行多个线程,只是线程交替执行且速度很快,相当于同时执行。而并行是同时执行多个线程,也就是多个cpu同时执行多个线程。在实际开发中,我们不需要...

jingzhi1230的博客 8187

Java 多线程理解

1.理解多线程 首先我们要了解什么是串行、并发、并行 串行:一个线程执行到底,相当于单线程。 并发:多个线程交替执行,抢占cpu的时间片,但是速度很快,在宏观角度看来就像是多个线程同时执行。 并行:多个线程在不同的cpu中同时执行。 并发与并行的区别: 并发严格的说不是同时执行多个线程,只是线程交替执行且速度很快,相当于同时执行。 而并行是同时执行多个线程,也就是多个cpu核心同时执行多个线程。 在实际开发中,我们不需要关心是否是并发还是并行,因为cpu会帮我们处理多线程,开发中可以认为多线程就是同时执行多

m0_46591169的博客 307

java中的多线程的使用

在实际的编程任务,项目开发中,为了提升效率,优化资源利用和增强用户体验,我们常常需要在程序运行中引入多线程,以此达到提高CPU利用率,提升程序响应性,简化复杂任务逻辑的功能。

2401_88650168的博客 1038
上一篇: MySQL的索引和事务(事务的隔离一看就懂)
下一篇: 多线程2(定时器的实现)
star050913
博客等级 码龄3年 277粉丝 33原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值