鞍山制作网站哪家好/博客seo教程
一、多线程
1.1进程和线程
进程:进程就是操作系统中运行的每一个应用程序。例如:微信,QQ
线程:线程是进程中的每一个任务。
多线程:在一个进程中,可以同时执行多个线程。同时完成多个任务。
并发:同时发生。多个线程同时完成任务时。
我们编写的应用程序运行时,也是一个进程。在我们进程中也是有线程的。
第一个现车给称为主线程:main方法就是第一个线程。
1.2 CPU轮转时间片
内存是作用是什么?处理程序数据。
CPU是中央处理器。程序想要运行必须使用CPU。
一个CPU同一时间只能处理一个程序运行。
一个程序想要运行必须抢到CPU
1.3 Thread类
Thread是线程的父类
(1) 构造方法
public Thread()
public Thread(String name)
name 是线程的名称
public Thread(Runnable target)
(2) 常用方法
public synchronized void start()
线程启动方法。 启动与运行现在不在是相同的概念。
线程启动之后,表示当前这个线程对象可以被运行。
public void run()
线程运行方法。
1.4 使用Thread类创建自定义的线程类
创建Thread类的子类。重写run的方法。为这个方法编写具体任务代码
Thread子类:
public class Thread01 extends Thread{@overridepublic void run(){System.out.println("abc");}
}
main方法:
public static void main(String[] args){Thread thread = new Thread01();thread.start();//启动
}
1.5 为什么要用多线程
示例代码:
public class Thread01 extends Thread{@overridepublic void run(){for(int i = 1;i <= 1000 ;i++){System.out.println(i+":abc");}}
}
public static void main(String[] args) {Thread thread = new Thread01();//创建了一个新的子线程。thread.start();//启动子线程。//thread.run();for(int i = 1;i<=1000;i++) {System.out.println(i+":000");}
}
输出:
1:000
1:abc
2:abc
3:abc
2:000
4:abc
3:000
在main方法中调用了thread.start();就表示在主线程中开辟了一个新的子线程。
主线程与子线程是并列的关系。二个线程之间的执行要通过抢CPU。
1.6 使用Runnable接口创建线程任务
线程:线程是在进程中的每一个任务。
Runnable接口就表示的任务接口。
@FunctionalInterface
public interfaceRunnable{public abstract void run();
}
编写Runnable接口的实现类。任务类
public class Runnbale02 implements Runnable{@Overridepublic void run() {for(int i = 1;i<=1000;i++) {System.out.println(i+":000");}}
}
使用任务类来创建一个线程对象
将任务类交给线程对象进行加载。线程启动时就可以调用任务类的run方法。
public static void main(String[] args) {//使用Runnable接口的实现类Runnbale02 runnbale02 = new Runnbale02();Thread thread02 = new Thread(runnbale02);thread02.start();
}
1.7 使用Callable接口编写任务类
在JDK1.5加入的关于线程的新的类。
解决了Runnable接口的二个问题:
1 异常没有抛出。调用线程启动时类,不知道在线程执行过程中有没有出现异常。
2 run方法没有返回值。调用线程结束之后。没有数据返回。
编写Callable接口下的实现类。任务类
public class Callable03 implements Callable<String> {@Overridepublic String call() throws Exception {for(int i = 1;i<=1000;i++) {System.out.println(i+":***");}return "任务Callable03执行完成!";}
}
1.8 使用线程池执行Callable接口的任务
(1) 线程池
池:容器。
线程池是存放大量线程对象的容器。
一个线程对象(Thread t)可不可能加载多个任务(Runnable r,Callable c)?
多个任务以串行方式,以先后顺序的方式进行执行。有多个任务可以同时使用同一个线程对象。
线程池:就是一个存放了大量线程对象的容器。
当有任务需要执行时,从线程池中拿一个线程对象。任务执行完成之后。将线程对象还给线程池。
(2)线程池Executor接口
实际开发时使用Executor接口的子接口ExecutorService
Submit 方法称为注册任务方法。
public interface ExcecutorService extends Executor{
<T>Future<T> submit(Callable<T> task);
}
这是一个创建线程池对象的工具类。
通过这个类的静态方法来获得不同的线程池对象
public class Executors {
返回一个有固定大小的线程池容器对象
public static ExecutorService newFixedThreadPool(int nThreads);
返回只有一个线程对象的线程池对象
public static ExecutorService newSingleThreadExecutor()
返回一个可变化的线程池对象
public static ExecutorService newCachedThreadPool()
}
(3) 返回值Future接口
用来接收Callable任务执行完成之后的返回值。
public interface Future<V> {
获取返回值对象的方式
V get() throws InterruptedException, ExecutionException;
}
public static void main(String[] args) {Callable03 callable03 = new Callable03();ExecutorService service = Executors.newFixedThreadPool(5);Future<String> future03 = service.submit(callable03);try {System.out.println(future03.get());} catch (Exception e) {e.printStackTrace();} finally {service.shutdown();}
}
1.9 线程状态
(1) 初始状态
一个刚被创建好的线程对象,就是初始状态的对象。
Thread t = new Thread(new Runnable02());
当前新创建的t线程对象就是初始状态
(2) 可运行状态
一个线程想要运行必须先抢到CPU。启动与运行是不同的概念。
当一个线程对象调用了start()方法启动了,但还没有抢到CPU时,都是一个可运行状态。
可运行状态的线程对象只做一件事:抢CPU。
(3) 运行状态
一个抢到CPU正在指向的线程对象。称为运行状态。
当一个运行装药的线程对象,CPU时间到期要转换为可运行状态。
(4) 终止状态
一个执行完成run()方法的线程对象,就是终止状态。
1.10 线程中的常用属性和方法
(1) name 属性
用来表示一个线程对象的名称。可以在创建线程对象时指定。也可以通过方法指定。
public class NameTest{public static void main(String[] args){Thread t = new Thread(new Runnable02(),"线程1");System.out.println(t.getName());}
}
(2) currentThread()
Thread类的静态方法。动态获取当前执行的线程对象。
public static native Thread currentThread()
public class Runnable02 implements Runnable{@Overridepublic void run(){for(int i = 1;i <= 10;i++){String name = Thread.currentThread().getName();System.out.println(name+"-"+i+":000");}}}
1.11 阻塞状态
线程对象运行过程中,出现以下情况:
1 等待IO。做标准输入时,用户需要冲控制台输入数据时。
2 sleep方法。当前线程休眠。
当线程遇到以上两种情况时,会进入阻塞状态。并会释放CPU。
二、本地线程对象ThreadLocal<T>类
2.1 本地线程对象是什么
1 本地线程对象其实是一个容器。而且是一个只能保存一个数据的容器对象。
2 这个容器在每一个不同的线程中,都有一份自己的实例。
3 每一个线程对象都使用自己的ThreadLocal类的实例。
4 当出现多个线程时,每一个线程中都有一个自己使用的ThreadLocal对象。
2.2 常用方法
public static void main(String[] args){ThreadLocal<String> local = new ThreadLocal<>();local.set("zhangsan");String s = local.get();System.out.println(s);
}
三、案例:取款与存款案例
3.1 编写两个任务
存款任务
取款任务
3.2 专家原则
专家原则:事情哪个对象最清楚(处理最直接),哪个对象负责
3.3 编写账号的类
public class Acount{private Double money;public Acount(Double money){this.money = money;}public Double getMoney() {return money;}public void setMoney(Double money) {this.money = money;}
}
3.4 编写DAO
public class AcountDAO{public void update(Acount acount,Double money){acount.setMonet(money);}
}
3.5 编写Service
public class AcountService{private AcountDAO acountDAO = new AcountDAO();public void deposit(Acount acount,Double money){double temp = acount.getMoney();temp = temp + money;acountDAO.update(acount,temp);}public void draw(Acount acount,Double money)throws Exception{double temp = acount.getMoney();if(temp > money){temp = temp - money;acountDAO.update(acount.temp);}else{throw new Exception("余额不足!");}}
}
3.6 编写任务类
任务类一定是与Service层对接。
存款任务:DepositRunnable
public class DepositRunnable implements Runnable{private AcountService service = new AcountService();private Acount acount;private Double money;public DepositRunnable(Acount acount,Double money){this.acount = acount;this.money = money;}@Overridepublic void run(){service.deposit(acount money);System.out.println("存款成功!"+acount.getMoney());}
}
取款任务:Draw
public class DrawRunnable implements Runnable{private AcountService service = new AcountService();private Acount acount;private Double money;public DrawRunnable(Acount acount, Double money) {this.acount = acount;this.money = money;}@Overridepublic void run() {try {service.draw(acount,money);System.out.println("取款成功!"+acount.getMoney());} catch (Exception e) {e.printStackTrace();System.out.println(e.getMessage()+"取款失败!"+acount.getMoney());}}
}
3.7 编写测试类
public static void main(String[] args) {Acount acount = new Acount(10000.0);DepositRunnable depositRunnable01 = new DepositRunnable(acount,10000.0);DepositRunnable depositRunnable02 = new DepositRunnable(acount,2000.0);DrawRunnable drawRunnable01 = new DrawRunnable(acount,5000.0);Thread t1 = new Thread(depositRunnable01,"自己");Thread t2 = new Thread(depositRunnable02,"父母");Thread t3 = new Thread(drawRunnable01,"女朋友");t1.start();t2.start();t3.start();}
问题!会出现数据不一致的情况。
账户的余额会经常变化。不是一个正确的固定的数值
四、线程不安全
线程不安全是指对各线程在操作数据时,数据不正确的情况。
线程不安全的几个条件:
1 多个线程 - 多线程
2 同时操作 - 并发
3 同一个数据 - 临界资源
4 破坏了不可分割的操作时 - 原子性
当以上的情况发生时,就有可能造成数据的不一致。这种情况就称线程不安全。
当多线程并发操作临界资源时,破坏了其原子性操作时,就有可能造成数据不一致。
解决方案:线程同步
五、线程同步
线程同步:多个线程以串行的方式执行。这种方式称为线程同步。
手拉手一起走,是异步。
串行的方式执行:是针对对临界资源的操作部分以串行的方式操作。
5.1 同步锁 synchronized
我们使用同步锁,来保证临界资源的原子性不被分割。
在执行原子性操作之前,先获取同步锁对象。之后再执行原子性代码。只有原子性代码执行完后曾之后。我们才会释放同步锁对象。
特殊注意:只有使用同一个同步锁的多个线程,才会以串行的方式执行。
必须要保证,多个线程使用的是同一个锁对象。才能叫多个线程的同步。
一般情况下,挑选临界资源作为锁对象更合适。
5.2 同步锁的使用方式一
synchronized(锁对象){
原子性操作代码;
}
加入同步锁的存款任务
public class DepositRunnable implements Runnable{private AcountService service = new AcountService();private Acount acount;private Double money;public DepositRunnable(Acount acount, Double money) {this.acount = acount;this.money = money;}@Overridepublic void run() {synchronized (acount) {System.out.println(Thread.currentThread().getName() + "-存款任务开始!");service.deposit(acount, money);System.out.println(Thread.currentThread().getName() + "-存款成功!" + acount.getMoney());System.out.println(Thread.currentThread().getName() + "-存款任务结束!");}}
}
加入同步锁的取款任务
public class DrawRunnable implements Runnable {private AcountService service = new AcountService();private Acount acount;private Double money;public DrawRunnable(Acount acount, Double money) {this.acount = acount;this.money = money;}@Overridepublic void run() {synchronized (acount) {System.out.println(Thread.currentThread().getName() + "-取款开始!");try {service.draw(acount, money);System.out.println(Thread.currentThread().getName() + "-取款成功!" + acount.getMoney());} catch (Exception e) {e.printStackTrace();System.out.println(Thread.currentThread().getName() + "-" + e.getMessage() + "取款失败!" + acount.getMoney());}System.out.println(Thread.currentThread().getName() + "-取款结束!");}}
}
测试类:
public class Test {public static void main(String[] args) {Acount acount = new Acount(10000.0);//临界资源DepositRunnable depositRunnable01 = new DepositRunnable(acount,10000.0);DepositRunnable depositRunnable02 = new DepositRunnable(acount,2000.0);DrawRunnable drawRunnable01 = new DrawRunnable(acount,5000.0);DrawRunnable drawRunnable02 = new DrawRunnable(acount,5000.0);Thread t1 = new Thread(depositRunnable01,"自己");Thread t2 = new Thread(depositRunnable02,"父母");Thread t3 = new Thread(drawRunnable01,"女儿");Thread t4 = new Thread(drawRunnable02,"老婆");t1.start();t2.start();t3.start();t4.start();}
}
相关文章:

入门Java第十五天 线程
一、多线程 1.1进程和线程 进程:进程就是操作系统中运行的每一个应用程序。例如:微信,QQ 线程:线程是进程中的每一个任务。 多线程:在一个进程中,可以同时执行多个线程。同时完成多个任务。 并发&#x…...

探索用卷积神经网络实现MNIST数据集分类
问题对比单个全连接网络,在卷积神经网络层的加持下,初始时,整个神经网络模型的性能是否会更好。方法模型设计两层卷积神经网络(包含池化层),一层全连接网络。选择 5 x 5 的卷积核,输入通道为 1&…...

MySQL 索引失效场景
1,前言 索引主要是为了提高表的查询速率,但在某些情况下,索引也会失效的情况。 2,失效场景 2.1 最左前缀法则 查询从索引最左列开始,如果跳过索引中的age列,那么age后面字段的索引都将失效,…...

Xcode开发工具,图片放入ios工程
Xcode开发工具,图片放入ios工程,有三种方式: 一:Assets Assets.xcassets 一般是以蓝色的Assets.xcassets的文件夹形式在工程中,以Image Set的形式管理。当一组图片放入的时候同时会生成描述文件Contents.jso…...

操作系统权限提升(十九)之Linux提权-SUID提权
系列文章 操作系统权限提升(十八)之Linux提权-内核提权 SUID提权 SUID介绍 SUID是一种特殊权限,设置了suid的程序文件,在用户执行该程序时,用户的权限是该程序文件属主的权限,例如程序文件的属主是root,那么执行该…...

直播 | StarRocks 实战系列第三期--StarRocks 运维的那些事
2023 年开春, StarRocks 社区重磅推出入门级实战系列直播,手把手带你从 Zero to Hero 成为一个 “StarRocks Pro”!通过实际操作和应用场景的结合,我们将帮你系统性地学习 StarRocks 这个当今最热门的开源 OLAP 数据库。本次&…...

KingabseES执行计划-分区剪枝(partition pruning)
概述 分区修剪(Partition Pruning)是分区表性能的查询优化技术 。在分区修剪中,优化器分析SQL语句中的FROM和WHERE子句,以在构建分区访问列表时消除不需要的分区。此功能使数据库只能在与SQL语句相关的分区上执行操作。 参数 enable_partition_pruning 设…...

Operator-sdk 在 KaiwuDB 容器云中的使用
一、使用背景KaiwuDB Operator 是一个自动运维部署工具,可以在 Kubernetes 环境上部署 KaiwuDB集群,借助 Operator 可实现无缝运行在公有云厂商提供的 Kubernetes 平台上,让 KaiwuDB 成为真正的 Cloud-Native 数据库。使用传统的自动化工具会…...

【数据挖掘】2、数据预处理
文章目录一、数据预处理的意义1.1 缺失数据1.1.1 原因1.1.2 方案1.1.3 离群点分析1.2 重复数据1.2.1 原因1.2.2 去重的方案1.3 数据转换1.4 数据描述二、数据预处理方法2.1 特征选择 Feature Selection2.2 特征提取 Feature Extraction2.2.1 PCA 主成分分析2.2.2 LDA 线性判别分…...

(四十六)大白话在数据库里,哪些操作会导致在表级别加锁呢?
之前我们已经给大家讲解了数据库里的行锁的概念,其实还是比较简单,容易理解的,因为在讲解锁这个概念之前,对于多事务并发以及隔离,我们已经深入讲解过了,所以大家应该很容易在脑子里有一个多事务并发执行的…...

【Android源码面试宝典】MMKV从使用到原理分析(二)
上一章节,我们从使用入手,进行了MMKV的简单讲解,我们通过分析简单的运行时日志,从中大概猜到了一些MMKV的代码内部流程,同时,我们也提出了若干的疑问?还是那句话,带着目标(问题)去阅读一篇源码,那么往往收获的知识,更加深入&扎实。 本节,我们一起来从源码层次…...

如何使用ADFSRelay分析和研究针对ADFS的NTLM中继攻击
关于ADFSRelay ADFSRelay是一款功能强大的概念验证工具,可以帮助广大研究人员分析和研究针对ADFS的NTLM中继攻击。 ADFSRelay这款工具由NTLMParse和ADFSRelay这两个实用程序组成。其中,NTLMParse用于解码base64编码的NTLM消息,并打印有关消…...

【Python学习笔记】第二十二节 Python XML 解析
一、什么是XMLXML即ExtentsibleMarkup Language(可扩展标记语言),是用来定义其它语言的一种元语言。XML 被设计用来传输和存储数据。XML 是一套定义语义标记的规则,它没有标签集(tagset),也没有语法规则(grammatical rule)。任何XML文档对任何…...

5分钟轻松拿下Java枚举
文章目录一、枚举(Enum)1.1 枚举概述1.2 定义枚举类型1.2.1 静态常量案例1.2.2 枚举案例1.2.3 枚举与switch1.3 枚举的用法1.3.1 枚举类的成员1.3.2 枚举类的构造方法1)枚举的无参构造方法2)枚举的有参构造方法1.3.3 枚举中的抽象方法1.4 Enum 类1.4.1 E…...

华为OD机试【独家】提供C语言题解 - 最小传递延迟
最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧文章目录 最近更新的博客使用说明最小…...

【Web前端】关于JS数组方法的一些理解
一、具备栈特性的方法unshift(...items: T[]) : number将一个或多个元素添加到数组的开头,并返回该数组的新长度。shift(): T | undefined从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度。二、具备队列特性的方法push(...items: T[]): …...

多智能体集群协同控制笔记(1):线性无领航多智能体系统的一致性
对于连续时间高阶线性多智能体系统的状态方程为: x˙i(t)Axi(t)Bui(t),i1,2..N\dot {\mathbf{x}}_i(t)A\mathbf{x}_i(t)B\mathbf{u}_i(t),i1,2..N x˙i(t)Axi(t)Bui(t),i1,2..N 下标iii代表第iii个智能体,ui(t)∈Rq1\mathbf{u}_i(t)\in R^{q \time…...

hadoop-Yarn资源调度器【尚硅谷】
大数据学习笔记 Yarn资源调度器 Yarn是一个资源调度平台,负责为运算程序提供服务器运算资源,相当于一个分布式的操作系统平台,而MapReduce等运算程序则相当于运行与操作系统之上的应用程序。 (也就是负责MapTask、ReduceTask等任…...

聊聊如何避免多个jar通过maven打包成一个jar,多个同名配置文件发生覆盖问题
前言 不知道大家在开发的过程中,有没有遇到这种场景,外部的项目想访问内部nexus私仓的jar,因为私仓不对外开放,导致外部的项目没法下载到私仓的jar,导致项目因缺少jar而无法运行。 通常遇到这种场景,常用…...

Flume 使用小案例
案例一:采集文件内容上传到HDFS 1)把Agent的配置保存到flume的conf目录下的 file-to-hdfs.conf 文件中 # Name the components on this agent a1.sources r1 a1.sinks k1 a1.channels c1 # Describe/configure the source a1.sources.r1.type spoo…...

DLO-SLAM代码阅读
文章目录DLO-SLAM点评代码解析OdomNode代码结构主函数 main激光回调函数 icpCB初始化 initializeDLO重力对齐 gravityAlign点云预处理 preprocessPoints关键帧指标 computeMetrics设定关键帧阈值setAdaptiveParams初始化目标数据 initializeInputTarget设置源数据 setInputSour…...

X和Ku波段小尺寸无线电设计
卫星通信、雷达和信号情报(SIGINT)领域的许多航空航天和防务电子系统早就要求使用一部分或全部X和Ku频段。随着这些应用转向更加便携的平台,如无人机(UAV)和手持式无线电等,开发在X和Ku波段工作,同时仍然保持极高性能水平的新型小尺寸、低功耗…...

推荐算法 - 汇总
本文主要对推荐算法整体知识点做汇总,做到总体的理解;深入理解需要再看专业的材料。推荐算法的意义推荐根据用户兴趣和行为特点,向用户推荐所需的信息或商品,帮助用户在海量信息中快速发现真正所需的商品,提高用户黏性…...

Android 系统的启动流程
前言:从开机的那一刻,到开机完成后launcher将所有应用进行图标展示的这个过程,大概会有哪一些操作?执行了哪些代码?作为Android开发工程师的我们,有必要好好的梳理一遍。既然要梳理Android系统的启动流程&a…...

自学5个月Java找到了9K的工作,我的方式值得大家借鉴 第二部分
我的学习心得,我认为能不能自学成功的要素有两点。 第一点就是自身的问题,虽然想要转行学习Java的人很多,但是非常强烈的想要转行学好的人是小部分。而大部分人只是抱着试试的心态来学习Java,这是完全不可能的。所以能不能学成Jav…...

Vue 3 第五章:reactive全家桶
文章目录1. reactive1.1. reactive函数创建一个响应式对象1.2. 修改reactive创建的响应式对象的属性2. readOnly2.1. 使用 readonly 函数创建一个只读的响应式对象2.2. 如何修改嵌套在只读响应式对象中的对象?3. shallowReactive3.1. 使用 shallowReactive 函数创建一个浅层响…...

【联机对战】微信小程序联机游戏开发流程详解
现有一个微信小程序叫中国象棋项目,棋盘类的单机游戏看着有缺少了什么,现在给补上了,加个联机对战的功能,增加了可玩性,对新手来说,实现联机游戏还是有难度的,那要怎么实现的呢,接下…...

优化基于axios接口管理的骚操作
优化基于axios接口管理的骚操作! 本文针对中大型的后台项目的接口模块优化,在不影响项目正常运行的前提下,增量更新。 强化功能 1.接口文件写法简化(接口模块半自动化生成) 2.任务调度、Loading调度(接口层…...

【Django功能开发】如何正确使用定时任务(启动、停止)
系列文章目录 【Django开发入门】ORM的增删改查和批量操作 【Django功能开发】编写自定义manage命令 文章目录系列文章目录前言一、django定时任务二、django-apscheduler基本使用1.安装django-apscheduler2.配置settings.py的INSTALLED_APPS3.通过命令生成定时记录表3.如何创…...

7个好用到爆的音频、配乐素材网站,BGM都在这里了
现在只要有一部手机,人人都能成为视频创作者。一个好的视频不能缺少的就是内容、配乐,越来越注重版权的当下,音效素材使用不当造成侵权的案例层出不穷。为了避免侵权,找素材让很多创作者很头疼。 今天我就整理了7个可以免费下载&…...