多线程学习笔记--第一章 多线程技能(1)

2023-05-16

1.什么是进程?
进程是操作系统结构的基础,是一次程序的执行;是一个程序及其数据在处理机上顺序执行时所发生的活动;是程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位。

2.什么是线程?
线程可以理解成是在进程中独立运行的子任务。

使用多线程的优点:

  1. 可以最大限度地利用CPU的空闲时间来处理其他任务。单任务的CPU利用率较低,特点是排队执行,即同步。使用多线程就是在使用异步。

3.继承Thread类
java JDK自带对多线程支持。实现多线程编程的方式主要有两种,一种是继承Thread类,另一种是实现Runnable接口
Thread类实现了Runnable接口,他们之间具有多态关系

使用继承Thread类的方式创建新线程,最大的局限就是不支持多继承,这是由于java语言的特点就是单根继承。所以,为了支持多继承,完全可以实现Runnable接口,两种方式创建线程在工作时性质一样。
使用多线程技术时,代码的运行结果与代码执行顺序或调用顺序无关(线程调用的随机性)。若多次调用start方法,会出现异常。


public class MyThread{

	public static void main(String[] args){
		Thread1 t1=new Thread1();
		t1.start();
		try{
			for(int i=0;i<10;i++){
				int time=(int)(Math.random()*1000);
				Thread.sleep(time);
				System.out.println("main="+Thread.currentThread().getName());
				
			}
		}catch(InterruptedException e){
			e.printStackTrace();
		}
		
	}
}

public class Thread1 extends Thread{
		@Override
		public void run() {
			try{
				for(int i=0;i<10;i++){
					int time=(int)(Math.random()*1000);
					Thread.sleep(time);
					System.out.println(i+" run="+Thread.currentThread().getName());
				}
			}catch(InterruptedException e){
				e.printStackTrace();
			}
		}
}
main=main
0 run=Thread-0
main=main
1 run=Thread-0
main=main
2 run=Thread-0
3 run=Thread-0
4 run=Thread-0
5 run=Thread-0
main=main
main=main
main=main
main=main
6 run=Thread-0
7 run=Thread-0
main=main
8 run=Thread-0
main=main
9 run=Thread-0
main=main

Thread.java类中的start方法通知“线程规划器”此线程已准备就绪,等待调用线程对象的run方法。这个过程就是让系统安排时间调用run方法,启动线程,具有异步执行的效果。如果调用代码thread,run()就不是异步执行,而是同步,那么此线程就不会交给“线程规划器”来处理,而是由main主线程来调用run()方法,也就是必须等run()方法中的代码执行完后才能执行后面的代码。另外,执行start顺序不代表线程启动顺序。


public class Thread2 extends Thread{
	private int i;
	public Thread2(int i){
		super();
		this.i=i;
	}
	
	@Override
	public void run() {
		// TODO 自动生成的方法存根
		System.out.println(i);
	}
}


public class MyThread{

	public static void main(String[] args){
		Thread2 t21=new Thread2(1);
		Thread2 t22=new Thread2(2);
		Thread2 t23=new Thread2(3);
		Thread2 t24=new Thread2(4);
		Thread2 t25=new Thread2(5);
		Thread2 t26=new Thread2(6);
		t21.start();
		t22.start();
		t23.start();
		t24.start();
		t25.start();
		t26.start();
	}
}

2
1
3
4
6
5

4.实现Runnable接口
如果欲创建的线程类已经有一个父类了,则不能继承Thread类,此时需要实现Runnable接口来解决这类情况。在Thread.java类的8个构造函数中,有Thread(Runnable target)和Thread(Runnable target,String name)可以传递Runnable接口。

由于Thread.java类也实现了Runnable接口,意味着构造函数Thread(Runnable target)还可以传入一个Thread类的对象,这样做完全可以将一个Thread对象中的run()方法交由其他线程进行调用。

5.实例变量和线程安全
自定义线程类中的实例变量针对其他线程有共享与不共享之分,涉及多线程交互。
(1)不共享数据


public class MyThread{

	public static void main(String[] args){
		Thread3 t21=new Thread3("A");
		Thread3 t22=new Thread3("B");
		Thread3 t23=new Thread3("C");
		
		t21.start();
		t22.start();
		t23.start();
		
	}
}


public class Thread3 extends Thread{
	private int count=5;
	public Thread3(String name){
		super();
		this.setName(name);//设置线程名字
	}
	@Override
	public void run() {
		// TODO 自动生成的方法存根
		super.run();
		while(count>0){
			count--;
			System.out.println("由"+this.currentThread().getName()+" 计算 count="+count);
		}
	}

}

由C 计算 count=4
由A 计算 count=4
由B 计算 count=4
由A 计算 count=3
由C 计算 count=3
由A 计算 count=2
由B 计算 count=3
由A 计算 count=1
由C 计算 count=2
由A 计算 count=0
由B 计算 count=2
由C 计算 count=1
由B 计算 count=1
由C 计算 count=0
由B 计算 count=0

(2)共享数据情况
多线程可以访问同一个变量。


public class MyThread{

	public static void main(String[] args){
		Thread4 thread=new Thread4();
		Thread a=new Thread(thread,"A");
		Thread b=new Thread(thread,"B");
		Thread c=new Thread(thread,"C");
		a.start();
		b.start();
		c.start();
	}
}


public class Thread4 extends Thread{
	private int count=5;
	
	@Override
	public void run() {
		// TODO 自动生成的方法存根
		super.run();
		count--;
		System.out.println("由"+this.currentThread().getName()+"计算count="+count);
	}
}

由C计算count=2
由B计算count=2
由A计算count=2

结果看出产生了“非线程安全”问题。修改代码:synchronized public void run()后运行得到:

由A计算count=4
由B计算count=3
由C计算count=2

通过加入synchronized关键字,使多线程在执行run方法时,以排队的方式进行处理。当一个线程调用run前,先判断run方法有没有被上锁。若上锁,则说明有其他线程在调用run方法,必须等待其他线程结束调用后才能执行run方法。synchronized可以对任意对象及方法加锁,而加锁的断码段称为“互斥区或”临界区”。当一个线程想要执行同步方法里面的代码时,线程首先尝试去拿这把锁,若拿到则执行,反之则不断地尝试去拿这把锁,直到拿到为止,而且是多个线程同时去争取这把锁。

非线程安全主要是指多个线程对同一个对象中的同一个实例变量进行操作时出现值被更改,值不同步情况,进而影响程序的执行流程。

6.i–与System.out.println()异常


public class MyThread{

	public static void main(String[] args){
		Thread5 thread=new Thread5();
		Thread a=new Thread(thread,"A");
		Thread b=new Thread(thread,"B");
		Thread c=new Thread(thread,"C");
		a.start();
		b.start();
		c.start();
	}
}


public class Thread5 extends Thread{
	/**
	 * 说明i--与sysout的异常
	 */

	private int i=5;
	@Override
	public void run() {
		// TODO 自动生成的方法存根
		System.out.println("i="+(i--)+"threadName="+Thread.currentThread().getName());
	}
}

i=5 threadName=C
i=4 threadName=A
i=4 threadName=B

println方法在内部是同步的,但是i–操作却是在进入println之前发生的,所以有发生非线程安全问题的概率。要避免这类问题应使用同步方法。

参考书籍《Java多线程编程核心技术》

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

多线程学习笔记--第一章 多线程技能(1) 的相关文章

  • 虚拟机中安装CMake工具

    https www cnblogs com yanqingyang p 12731855 html
  • 寻路系统:动态障碍物

    寻路的相关参数 需要先勾选 游戏场景中所有需要烘焙路径信息的游戏对象状态为 static 然后点开windos菜单下的navigation窗口进行烘培 Navigation Static xff1b 表示该游戏对象是否参与导航网格的烘培 G
  • Ubuntu18.04下使用cmake编译一个OpenCV程序(编写CMakeLists.txt文件)

    导航 1 安装OpenCV1 1首先安装OpenCV 1 2定位OpenCV 2 创建一个项目3 编写一个基础OpenCV程序4 编写CMakeLists txt文件 为了记录以及防止遗忘 xff0c 备份一个大致能满足运行的CMakeLi
  • linux下最全curl命令使用方式学习和拓展

    为什么要使用curl命令 xff1f curl命令可以帮助我们在linux服务内部通讯 xff0c 排查接口是否能够正确调用 xff0c 外网的接口是否有防火墙限制 xff0c 内网的请求可以快速帮我们获取接口参数返回 xff0c 并且调试
  • 【传感器标定】kalibr 标定工具箱问题汇总

    文章目录 写在前面一 运行一段时间报错 96 Spline Coefficient Buffer Exceeded Set larger buffer margins 96 的解决方法1 问题描述2 解决方法参考链接 写在前面 kalibr
  • C++中的Vector存放指针的清空问题

    C 43 43 中的Vector存放指针的清空问题 一 写在前面二 参考做法参考链接 这两个链接写得挺好 xff0c 可以参考下 一 写在前面 C 43 43 很难的一个重要原因就是内存管理的问题 xff0c 因为你既要管理申请内存 xff
  • find_package(xxxx REQUIRED)找不到路径的全平台通用解决办法

    相信刚学cmake c 43 43 的朋友们在编译的时候一定被这个问题折磨许久哈 然后怎么搜怎么添加都有问题 xff0c 仔细研究了我才发现这个地方不同的索引机制 xff0c 但是表面上都是 find package xxxx REQUIR
  • STC51-串口通信

    1 并行与串行基本通信方式 随着单片机系统的广泛应用和计算机网络技术的普及 xff0c 单片机的通信功能愈来愈显得重要 单片机通信是指单片机与计算机或单片机与单片机之间的信息交换 xff0c 通常单片机与计算机之间的通信我们用的较多 通信有
  • qt种实现搜索栏功能

    引言 在搜索栏种输入要搜索的文本 xff0c 就会出现相关联的文本提示 xff0c 这是可以通过鼠标选中要搜索的文本 xff0c 或者通过上下键选中要搜索的文本 效果 效果图如下所示 xff1a 实现 下面是相关的代码实现 xff0c 读者
  • orangePi3 TLS烧录启动、wifi配置和ssh登录、烧录进内置emmc flash

    orangePi3 TLS烧录启动 wifi配置和ssh登录 烧录进内置emmc flash 烧录镜像到TF卡启动 镜像下载 官方镜像地址 xff1a http www orangepi cn html hardWare computerA
  • C/C++——代码的编译和运行

    1 编译过程 每种高级语言都有对应的编译器 xff0c 而且针对不同指令集架构的CPU会提供不同的编译器 本文以C语言为例 xff0c CPU指令集架构不做前提约束 xff0c 实际上同一种语言也只有在狭义的编译阶段有所区别 xff0c 其
  • Arduino UNO GPS 制作 里程表 经纬度

    机缘 上过月买了一个GPS模块 xff0c 然后我用esp32读取GPS数据 xff0c 并使用LVGL显示GPS信息 期间踩了很多坑 xff0c 我用乐鑫的IDF开发 xff0c 自己写了一个GPS信息提取方法 xff0c BUG很多 x
  • socket编程——UDP协议(C语言编程)

    1 收发信息 ssize t sendto int socket void message size t length int flags struct sockaddr dest addr socklen t dest len 返回值 l
  • 【C语言之线性表链式存储结构】

    C语言之线性表链式存储结构 文章目录 C语言之线性表链式存储结构前言一 线性表链式存储结构定义二 相关概念1 结点1 头指针 三 代码描述1 单链表结点定义1 单链表的创建2 单链表的查找3 在单链表中 xff0c 替换某一个位置的数据4
  • unsigned char* (uchar*) 转为QImage

    场景 xff1a 有一副图像 xff0c 事先已经因为各种需要被读取到了内存中 xff0c 且不可再根据路径读取 xff0c 只能读取内存中的数据转为QImage 百度过好久 xff0c 没有一个帖子说的特别详细 xff0c 解释的特别清楚
  • 卷积的含义-详解

    原文链接 xff1a 点击此处看知乎原文 最近需要用到卷积对图像进行处理 xff0c 不明白卷积的含义 xff0c 找资料的时候在知乎找到一个很优秀的评论 xff0c 特此记录一下 以下内容来自于原文复制 xff1a 对卷积的困惑 卷积这个
  • 图像处理-直方图均衡化(C++实现,不依赖opencv)

    近来接触图像处理领域 xff0c opencv入门之后 xff0c 想自己动手实现一些算法 xff0c 先从直方图均衡化开始吧 xff01 我使用的图像文件是只包含数据yuv格式图像 xff0c 以后等需要的时候再处理从普通格式 xff08
  • 图像处理-Sobel边缘检测(C++实现,不依赖opencv)

    边缘检测一直是图像处理中比较热门的一块 xff0c 今天简单实现了下sobel算法 先上图 xff1a 原图 xff1a Sobel处理 彩图 xff1a Sobel处理 灰度图 xff1a 可以看到在不复杂的情况下 xff0c Sobel
  • 图像处理-高斯滤波和升级版Side Window版高斯滤波(C++实现,无需opencv)

    图像处理绕不开的一个环节就是去燥 xff0c 去掉各式各样的噪声来保证图像的质量 今天将高斯滤波实现了下 xff0c 在此稍作记录 以往惯例 xff0c 先上图 xff1a 原图 xff1a 高斯滤波 xff1a Side Window版高
  • Linux下,使用nginx+ffmpeg+video.js实现直播效果(含centos7环境配置步骤)

    前言 近来因为项目需要 xff0c 需要做一个把视频解码然后推流 xff0c 在浏览器播放的功能 然后查资料 找demo xff0c 最终决定使用FFmpeg 43 nginx来完成相应功能 xff0c 过程颇为心酸 xff0c 在此做下笔

随机推荐

  • 使用QMap保存数据时,若出现相同的键,可以在不改变原有的变量存储选型基础上,使用insertMulti函数来解决

    场景 问题发生场景解决办法方案一方案二方案三 xff08 重点 xff09 针对方案三的示例 问题发生场景 本来项目中选型选择的是QMap来存储相应的键值对 xff0c 根据Map中的键的顺序取出对应的值 但是在使用的过程中 xff0c 发
  • C语言,声明和实现放在头文件中

    将头文件和实现放在同一个文件中 普通函数与静态函数是有区别的 静态函数 xff1a static h ifndef CRND INCLUDE CRND H define CRND INCLUDE CRND H static int pore
  • C++的编译过程详解

    C C 43 43 编译过程 C C 43 43 编译过程主要分为4个过程 编译预处理编译 优化阶段汇编过程链接程序 一 编译预处理 xff08 1 xff09 宏定义指令 xff0c 如 define Name TokenString x
  • BA(Basic authentication)认证实践

    1 概念介绍 Basic authentication xff1a 是一种最简单的对Web资源进行访问控制的方法 xff0c 属应用层的安全保障手段 常用的签名算法有 xff1a base64 HmacSHA1 1 xff09 优点 xff
  • 累加校验和C语言实现

    发送方 xff1a 对要数据累加 xff0c 得到一个数据和 xff0c 对和求反 xff0c 即得到我们的校验值 然后把要发的数据和这个校验值一起发送给接收方 接收方 xff1a 对接收的数据 包括校验和 进行累加 xff0c 如果得到0
  • C++项目工程在Linux环境开发、部署和运行问题

    背景 当我们自己开发的项目程序需要在linux上进行部署 调试时 xff0c 项目代码完整拷贝过去之后 xff0c 直接运行我们自己的可执行程序 xff0c 往往提示找不到所相关的 so库 xff0c 会报错 这是因为 xff0c 系统只会
  • Jetson Xavier NX上安装ROS、Cartographer、基于D435i的Yolov5+TensorRT7的流程及问题解决

    主要记录下自己在Jetson Xavier NX上运行ROS Cartographer 基于D435i的Yolov5 43 TensorRT的系统环境配置流程 xff0c 经过了无数次在ARM上的安装 xff0c 这次是最流畅的一次环境配置
  • 计算机进制转换:二进制、八进制、十进制、十六进制

    一 什么是进制 在生活中 xff0c 我们通常都是使用阿拉伯数字计数的 xff0c 也就是10进制 xff0c 以10为单位 xff0c 遇10进一 xff0c 所以是由0 xff0c 1 xff0c 2 3 4 5 6 7 8 9组成的
  • 摘要认证,使用HttpClient实现HTTP digest authentication

    文章目录 前言一 四个过程二 过程细节三 HttpClient 代码示例 前言 今天工作需要做了摘要认证 xff08 digest authentication xff09 xff0c 下面就工作中遇到的问题及过程做一个总结 一 四个过程
  • C语言之带参数的宏

    这两天在学习C语言 xff0c 发现宏定义挺有意思 xff0c 可以减少代码量 带参宏定义 的一般形式为 define 宏 名 形参表 字符串 带参宏调用 的一般形式为 xff1a 宏 名 实参表 xff1b define M X Y X
  • visual studio升级

    visual studio升级 概述升级步骤温馨提示 概述 有时处于开发要求或者安全要求 xff0c 需要将visual studio升级到最新的版本 本篇文章记录一下如何升级 升级步骤 1 找到visual studio的安装路径下的安装
  • STL中那些好用的东西!(持续更新)

    一 数据结构部分 1 set amp map xff08 后续持续更新 xff09 2 queue xff08 priority queue xff09 queue lt int gt a 定义 a push i 压入 a pop 弹出 a
  • 工业机器人虚拟仿真设计

  • HTTP详解

    一 什么是HTTP xff1f HTTP xff08 HyperText Transfer Protocol xff0c 超文本传输协议 xff09 是一个简单的请求 响应协议 xff0c 它通常运行在TCP之上 xff08 应用层 xff
  • android练习之为 TextView 添加监听器 ,添加后退按钮 ,从按钮到图标按钮

    为 TextView 添加监听器 NEXT按钮不错 xff0c 但如果用户单击应用的TextView文字区域 xff08 地理知识问题 xff09 xff0c 也可以跳转 到下一道题 xff0c 用户体验会更好 添加后退按钮 为GeoQui
  • ORA-01918: 用户 'SCOTT' 不存在 解决方法

    SQL gt alter user scott account unlock alter user scott account unlock 第 1 行出现错误 ORA 01918 用户 SCOTT 不存在 找到scott sql 文件 S
  • idea 里form表单action提交servlet文件出现报错

    由于在action的字符串中加了空格 xff0c 导致于于url pattern不匹配 xff0c 所以报错
  • 数据结构——二维数组

    二维数组可以理解为数组的数组 二维数组组织为矩阵 xff0c 可以表示为行和列的集合 但是 xff0c 创建二维数组以实现关系数据库外观相似的数据结构 它提供了一次容纳大量数据的便利性 xff0c 可以在任何需要的地方传递给任意数量的功能
  • 数据结构——链表

    链表是一种随机存储在内存中的节点的对象集 节点包括两个字段 xff0c 即存储在该地址的数据和包含下一节点地址的指针 链表的最后一个节点包含指向null的指针 1 链表的用途 链表不需要连续存在于存储器中 节点可以是存储器中任何位置并链接在
  • 多线程学习笔记--第一章 多线程技能(1)

    1 什么是进程 xff1f 进程是操作系统结构的基础 xff0c 是一次程序的执行 xff1b 是一个程序及其数据在处理机上顺序执行时所发生的活动 xff1b 是程序在一个数据集合上运行的过程 xff0c 它是系统进行资源分配和调度的一个独