Java-多线程基础篇

news2024/12/24 3:25:59

前言:

以下是看马老师的视频以及自己阅读《Java多线程编程实战指南》所总结的基础内容,只是个人理解,如有不对还请大家指正。

1.线程的概念:

来自于百度百科:线程是独立调度和分派的基本单位。在Unix System V及SunOS中也被称为轻量进程(lightweight processes),但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。

2.线程相关概念:

2.1 串行,并行,并发

计算机的任务/事情所耗费总时间是包括:实际做事时间+等待时间,因为有一些任务是需要等待的,如IO任务。假设A总15(实际做事时间5,等待10),B总10(做事2,等待8),C总10(做事10,等待0)。

如下图,串行容易理解,先做A,再做B,再做C,所以15+10+10

并发好处是上个任务等待时间可以进行下个任务开始做事,所以是5+2+10=17

并行就是极致的并发,理想型并发,总时长取决于最长时间,所以是15。

从硬件角度,在一个处理一次只能运行一个线程情况下,处理器是利用时间片分配技术来实现同一个时间段运行多个线程,因此一个处理器可以实现并发,并发这种方式更多是在多核上同一时间运行一个线程来实现。

还有一点,并发不一定会比串行来的效率更高或者效率提高那么明显。

2.2 竞态:

多线程编程中,有时候相同的输入,程序输出有时候正确,有时候错误,计算结果的正确性与时间有关的现象称为竞态。由于竞态常常伴随这脏读,简单的例子就是 多个线程都对某个共享变量进行递增操作,一个线程在写变量,但是这个递增动作还没完成,而另个线程读取的值是之前的值,导致了它递增的动作还是再原来值增加,覆盖了前一个线程的值,导致两次递增的结果是相同的。

竞态最常见的典型实例是在:read-modify-write(读-改-写)和check-then-act(检测后行动)

2.3 安全性

一个类在单线程环境下能够正常运行,并且在多线程环境下,使用方不必为其改变的情况下也能运行正常,那么我们就称为线程安全,对应的这个类是具有线程安全的。反之,单线程运行正常,多线程则无法正常运行,这个类就是非线程安全的。

2.4 原子性

原子字面意思是不可分割,对于涉及共享变量访问的操作,若该操作从其执行线程以外的任意线程来看是不可分割的,那么该才做就是原子操作,相应的我们称该操作具有原子性。

这边不可分割,是指访问(读、写)某个共享变量的操作从其执行线程以外的任意线程来看,该操作要么已经执行要么尚未发生,其他线程不会“看到”该操作执行了部分中间结果。两种方式来实现原子性,一种就是使用锁,锁具有排他性,通常是软件层面实现,一种是处理器专门CAS(compare-and-Swap)指令,可以认为是一种“硬件锁”。

2.5 可见性

多线程环境下,一个线程对某个共享变量进行更新后,后续访问该变量的线程可能无法立刻读取到这个更新结果,甚至永远也无法读取到这个更新结果。

2.6 有序性和重排序

有序性是指在什么情况下一个处理器上运行的一个线程所执行的内存访问操作在另个处理器上运行的其他线程看起来乱序的。两个操作在代码上是有先后关系的,但是编译器可能改变两个操作的先后顺序,处理器可能不是按照程序的代码指定顺序执行指令,这种现象就是重排序,它是一种内存访问(读和写)的一种优化,不影响单线程正确性提高程序性能。

2.7 锁

这里面涉及了很多概念,原子性,可见性,重排序,那么一个好的多线程编程肯定是要保障原子性+可见性+有序性,很容易联想到就是,一个共享数据一次只能被一个线程访问,锁也是这种机制保障了线程安全的同步机制。

线程可以获得或者释放对应的锁,在这段时间内执行的代码成为“临界区”。锁有内部锁(synchronized关键字)和显式锁(java.concurrent.locks.lock接口实现类)。

锁具有排他性,也就是互斥,所以它满足了代码只能被一个线程执行,自然而然具有不可分割的特性,所以具备了原子性。同时锁的机制,在锁释放时候回冲刷处理器缓存动作,保证锁改变的共享变量能够被其他线程同步,所以保证了可见性。最后,锁能够保证有序性,就是在其他线程看来,临界区里面共享变量是同一时刻更新的,但是有一点需要注意,临界区内的任意两个操作依然可以再临界区之内被重新排序(不会排序到临界区外),这里结合后面可见性例子可以参考一下。

锁还有一个概念,可重入性,一个线程持有一个锁时候,还能继续成功申请该锁,就是可重入的锁,反之就是非可重入的锁。

线程同步机制底层是通过“内存屏障”来实现的,其作用的是保证持有锁线程能够读取到最新数据,并且持有线程对共享数据所做的更改,对后续线程可见,这里原文有很多,就不展开讲。

2.8 volatile关键字

书本上写着volatile关键字的作用是,保障可见性,保障了有序性,保障了long/double型变量读写操作的原子性。马老师课上说的这样,volatile保证了可见性,防止代码重排序。

3.线程启动方式:

java线程启动方式其实是有三种,一种是类继承Thread,一种是类实现Runnable接口,在new并将相应类对象输入Thread对象中,代码是第三种其实是第二种的变形。其实还有一种方式,是线程池的方式,Executors.newCacheThread方式。

public class Thread_base {

    private static class T1 extends Thread{


        @Override
        public void run() {
            System.out.println("T1");
        }
    }

    private static class T2 implements Runnable{
        @Override
        public void run() {
            System.out.println("T2");
        }
    }

    public static void main(String[] args) {
        new T1().start(); //第一种
        new Thread(new T2()).start(); //第二种
        new Thread(()->{
            System.out.println("hello new");
        }).start(); //这种其实是第二种变形

    }
}

3.1线程状态的转换:

NEW,一个已创建而为启动线程,由于一个线程实例只能被启动一次,因此一个线程只可能有一个该状态。

RUNNABLE,一个复合状态包括两个子状态,READY和RUNNING。前者表示处于该状态线程可以被线程调度器进行调度而使之处于RUNNING状态,后者表示处于该状态正在运行,即对象的run方法对应指令正在处理器执行。

BLOCKED,一个线程发起一个阻塞式IO操作,或者申请一个由其他线程持有独占资源(锁),处于该状态,BLOCKED状态的线程并不会占用处理器资源。

WAITING,一个线程执行了某个特别方法就会处于这种等待其他线程执行另外一些特定操作的状态。包括Object.wait(),Thread.join()和lockSupport.park(Object),而能从WAITING变更为RUNNABLE的相应方法包括:Object.notify()/notifyALL()和LockSupport.unpart(Object)

TIMED_WAITING:该状态和WAITING类似,差别在于处于该状态的线程并非无限制等待其他线程执行特定操作,而是处于带有时间限制的等待状态。当其他线程没有在指定时间执行线程所期望的特定操作时,该线程的状态自动转换为RUNNABLE.

TERMINATED:已经执行结束的线程处于该状态.Thread.run()正常返回或者由于抛出异常而提前终止都会导致对应线程处于该状态。

一个线程在其整个生命周期中,只可能有一次处于NEW状态和TERMINATED状态。

3.2线程常用方法:

待续

参考文献

《Java多线程编程实战指南-核心篇》

马士兵多线程课程

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

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

相关文章

测试行业爬了7年,从功能测试到高级测试,工资也翻了好几倍

我在测试行业爬了7年。从功能测试到现在成为高级测试,我的工资也翻了好几倍。 入门阶段(功能测试) 个人认为,测试的前景还不错,只要你肯努力;刚出来的时候在鹅厂做外包功能测试。每天都很悠闲。点了两年&a…

Java16新增特性

前言 前面的文章,我们对Java9、Java10、Java11、Java12 、Java13、Java14、Java15 的特性进行了介绍,对应的文章如下 Java9新增特性 Java10新增特性 Java11新增特性 Java12新增特性 Java13新增特性 Java14新增特性 Java15新增特性 今天我们来一起看一下…

【深圳1024开发者城市聚会】主理人视角的聚会现场,一起来看看有啥不一样的东西

【深圳1024开发者城市聚会】主理人视角的聚会现场,一起来看看有啥不一样的东西 今年的1024,我们在深圳,玩点不一样的… 文章目录 1 活动背景2 活动宣传3 活动准备4 活动现场布置会场会场引导签到深圳站视频展播前半程议题分分享简单茶歇后半场…

轻量封装WebGPU渲染系统示例<28>- MRT纹理(源码)

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/rendering/src/voxgpu/sample/MRT.ts 当前示例运行效果: 此示例基于此渲染系统实现,当前示例TypeScript源码如下: export class MRT {private mRscene new RendererScene();initial…

错误:FUNCTION simple_notebook.count does not exist.解决方法

0 引入问题 小王:你这个数据有问题啊,有时候还会报错 小腾:怎么会有问题呢,代码写的一点毛病也没有 小王:没问题怎么会报错,你赶紧看看,项目上线甲方看到了报给老板咱俩就寄了 小腾&#xff1a…

【LeetCode刷题笔记】二叉树(一)

102. 二叉树的层序遍历 解题思路: 1. BFS广度优先遍历 ,使用队列,按层访问 解题思路: 2. 前序遍历 , 递归 ,在递归方法参数中,将 层索引

对于联邦政府来说,零信任只是一个开始

今年早些时候,美国空军国民警卫队的一名拥有绝密安全许可的成员向社交媒体平台 Discord 泄露了国家安全文件。 据报道,这些文件迅速传播到其他平台,其中包含有关美国和北约在俄罗斯军事行动的敏感信息,包括有关预期武器交付的详细…

Python 如何实现 Strategy 策略设计模式?什么是 Strategy 策略设计模式?

策略模式(Strategy Design Pattern)是一种对象行为型设计模式,它定义了一系列算法,并使得这些算法可以相互替换,使得客户端代码可以独立于算法的变化而变化。策略模式属于对象行为模式。 主要角色: 策略接口…

postman调用接口报{“detail“:“Method \“DELETE\“ not allowed.“}错误, 解决记录

项目是python代码开发, urls.py 路由中访问路径代码如下: urlpatterns [path(reportmanagement/<int:pk>/, views.ReportManagementDetail.as_view(), namereport-management-detail),] 对应view视图中代码如下: class ReportManagementDetail(GenericAPIView):"…

cgo与调用c的回调函数指针

cgo直接调用函数&#xff0c;使用基本数据类型非常简单&#xff0c;包括一些结构体也比较简单&#xff0c;嵌套的稍微复杂些&#xff0c;但也可以&#xff0c;但有的时候&#xff0c;cgo调用c函数&#xff0c;会需要传递一个回调函数的指针&#xff0c;这时候就比较复杂了&…

Arcgis打开报错error code=-15

Provide your license server administrator with the following information: Error Code -15 问题描述 原因 长时间闲置后&#xff0c;license server administrator会关闭服务。再次打开之后会出现这个报错 解决方案 重启或者按下述做法&#xff1a; 打开任务管理器&am…

【无标题】通用工作站设计方案:ORI-D3R600服务器-多路PCIe3.0的双CPU通用工作站

ORI-D3R600服务器-多路PCIe3.0的双CPU通用工作站 一、机箱功能和技术指标&#xff1a; 系统 系统型号 ORI-SR630 主板支持 EEB(12*13)/CEB(12*10.5)/ATX(12*9.6)/Micro ATX 前置硬盘 最大支持8个3.5寸(兼容25寸)SATA硬盘 2*2.5(后置) 电源类型 CRPS元余电源&#xff0…

【Verilog语法】

Verilog语法 1. Verilog语法1.1 拼接运算符1.2 运算符优先级1.3 注释1.4 关键字1.5 模块结构1.6 结构语句1.7 赋值语句1.8 条件语句1.9 状态机1.10 OSI七层模型 1. Verilog语法 1.1 拼接运算符 1.2 运算符优先级 1.3 注释 1.4 关键字 1.5 模块结构 1.6 结构语句 1.7 赋值语句 …

【Java 进阶篇】JQuery DOM操作:Class属性的舞蹈魔法

在前端的世界中&#xff0c;JQuery如同一位舞者&#xff0c;通过灵活的舞步为我们展示了操纵HTML元素的艺术。而在这场舞蹈的精彩演出中&#xff0c;Class属性的操作是一项极富魅力的技艺。在本篇博客中&#xff0c;我们将深入研究JQuery DOM操作中的Class属性操作&#xff0c;…

pytest-bdd快速示例和问题解决

BDD 与 pytest-bdd BDD 即 Behavior-driven development&#xff0c;行为驱动开发。BDD行为驱动是一种敏捷开发模式, 重点在于消除开发/测试对需求了解的歧义及用户场景的验证。 pytest-bdd 是一个BDD测试框架&#xff0c;类似于behave, cucumber。它可以统一单元测试和功能测…

【数据结构】——单链表(增删查改)

目录 前言&#xff1a; 一&#xff1a;单链表的特点 ​编辑 二&#xff1a;单链表实现 单链表定义 2.1申请节点&#xff08;初始化&#xff09; 2.2单链表尾插 ​编辑 2.3单链表打印 2.4单链表头插 2.5单链表尾删 2.6单链表头删 2.7单链表查找 2.8在目标位置后面插入…

三国杀中的概率学问题4——曹冲

前言 这篇文章是围绕曹冲的称象技能展开的一些数学上的讨论&#xff0c;将涉及到积分、概率论等知识&#xff0c;并会做很多拓展。 值得说明的是&#xff0c;本文受到了这篇文章的一些启发。 连续情形1 先来看一个连续情形的问题。 问题一&#xff1a;假设每张牌的点数是0~1…

JVM:卡表元素如何维护?(写屏障)

写屏障 上面使用记忆集解决了缩减GC Roots扫描范围的问题&#xff0c;现在又抛出来一个新的问题&#xff0c;卡表元素如何维护的呢&#xff1f;&#xff0c;例如它们何时变脏、谁来把它们变脏等。 何时变脏这个问题应该很明确的&#xff0c;原则上应该发生在引用类型字段赋值…

编译原理-语法分析-自上而下分析

文章目录 语法分析器的功能自上而下分析面临的问题LL&#xff08;1&#xff09;分析法左递归的消除直接左递归非直接左递归 消除左递归的算法消除回溯、提左因子FIRST提左因子FOLLOW集 LL(1)的分析条件LL(1)文法构造FIRST和FOLLOW集合构造每个文法符号的FIRST集合构造FOLLOW集合…