day24_多线程进阶
今日内容
上课同步视频:CuteN饕餮的个人空间_哔哩哔哩_bilibili
同步笔记沐沐霸的博客_CSDN博客-Java2301
零、 复习昨日
一、作业
二、线程安全的集合
三、死锁
四、线程通信
五、生产者消费者
六、线程池
零、 复习昨日
创建线程的几种方式 1) 继承 2) 实现Runnable 3) callable接口 Future接口 4) 线程池
启动线程的方法 start()
线程的几种状态
什么是线程不安全
setName getName
Thread.currentThread()
join
sleep
synchronized
一、作业
售卖后车票
package com.qf.homework;/*** --- 天道酬勤 ---** @author QiuShiju* @desc*/
public class Window implements Runnable {// 票(加static,被该类所有对象共享)private static int ticket = 100;// 售票任务@Overridepublic void run() {while (true) {synchronized (Window.class) {if (ticket > 0) {try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace( );}System.out.println(Thread.currentThread( ).getName( ) + "有余票,正在售出" + ticket);ticket--;} else {System.out.println("票已售完");return;}}}}
}
public static void main(String[] args) {new Thread( new Window() ,"窗口1").start();new Thread( new Window() ,"窗口2").start();new Thread( new Window() ,"窗口3").start();}
二、线程安全的集合[了解]
StringBuffer是线程安全的,是因为每个方法都加上synchronized,即都是同步方法
StringBuilder没有加
ArrayList是线程不安全
Vector 是线程安全
HashMap 是线程不安全
Hashtable 是线程安全
比HashMap安全,比Hashtable快,即安全又快的集合ConcurrentHashMap[很重要]
三、死锁[了解]
死锁: 互相持有对方的锁还不释放
public class MyLock {static Object zuo = new Object();static Object you = new Object();
}
public class Boy extends Thread{@Overridepublic void run() {synchronized (MyLock.zuo){System.out.println("男朋友-拿到左筷子" );synchronized (MyLock.you) {System.out.println("男朋友-拿到右筷子,开吃" );}}}
}
public class Girl extends Thread{@Overridepublic void run() {synchronized (MyLock.you){System.out.println("女朋友-拿到右筷子" );synchronized (MyLock.zuo) {System.out.println("女朋友-拿到左筷子,开吃" );}}}
}
public class TestDeadLock {public static void main(String[] args) {new Boy().start();new Girl().start();}
}
男生先拿到zuo锁,再去获得you锁即可吃饭
但是you锁在女生那里,女生需要获得zuo锁才能吃饭
即 男生需要的you锁被女生拿着,女生需要的zuo锁被男生拿着
互相持有对方的锁,还不释放,就会出现"死锁" 程序卡死,不往下执行,持续阻塞
四、线程通信[熟悉]
4.1 介绍
线程通信,就是线程之间产生联系.
即通知,例如线程A执行到一定时候会
停下
,同时通知另外的线程B执行,
线程B执行到一定时候,也停下,通知线程A执行
以上操作需要Object类的方法
- wait() 让当前线程等待
- notify() 唤醒一个处于等待状态的线程
- notifyAll() 唤醒所有处于等待状态的线程
4.2 两个个线程通信
需求: 昨天打印机方法,让print1()和print2()方法交替执行
package com.qf.notify;/*** --- 天道酬勤 ---** @author QiuShiju* @desc 打印机类*/
public class Printer {// 具体哪台打印机执行的标志private int flag = 1;// 现在使用同步方法,print1和print2方法由同一个对象打印机对象调用// print1方法和print2方法锁是同一个,是this,即打印机对象public synchronized void print1() {if (flag != 1) {try {// 锁是谁,就用谁调用wait// 当前线程就陷入等待,会让出资源释放锁this.wait();} catch (InterruptedException e) {e.printStackTrace( );}}System.out.print("1 ");System.out.print("2 ");System.out.print("3 ");System.out.print("4 ");System.out.print("\r\n");// 干完活,修改标志flag = 2;// 通知另外一个处于等待状态的线程// 锁是谁,用谁调用方法this.notify();}public synchronized void print2() {if (flag != 2) {try {this.wait();} catch (InterruptedException e) {e.printStackTrace( );}}System.out.print("A ");System.out.print("B ");System.out.print("C ");System.out.print("D ");System.out.print("\r\n");flag = 1;this.notify();}
}
// 测试
public class TestNotify {public static void main(String[] args) {Printer printer = new Printer( );new Thread(){@Overridepublic void run() {while (true){printer.print1();}}}.start();new Thread(){@Overridepublic void run() {while (true){printer.print2();}}}.start();}
}
换用同步代码块实现
package com.qf.notify;/*** --- 天道酬勤 ---** @author QiuShiju* @desc 打印机类*/
public class Printer {// 锁对象private Object obj = new Object();// 具体哪台打印机执行的标志private int flag = 1;// 现在使用同步方法,print1和print2方法由同一个对象打印机对象调用// print1方法和print2方法锁是同一个,是this,即打印机对象public void print1() {// 同步代码块,现在锁是字节码文件synchronized(Printer.class) {if (flag != 1) {try {// 锁是谁,就用谁调用wait// 当前线程就陷入等待,会让出资源释放锁// 用字节码锁来调用wait方法Printer.class.wait( );} catch (InterruptedException e) {e.printStackTrace( );}}System.out.print("1 ");System.out.print("2 ");System.out.print("3 ");System.out.print("4 ");System.out.print("\r\n");// 干完活,修改标志flag = 2;// 通知另外一个处于等待状态的线程// 只能唤醒在此对象监视器(加过锁的)上等待的单个线程.// 如果没有加锁,直接调用该方法唤醒线程,会报错IllegalMonitorStateException// 锁是谁,用谁调用方法Printer.class.notify( );}}public void print2() {synchronized( Printer.class) {if (flag != 2) {try {Printer.class.wait( );} catch (InterruptedException e) {e.printStackTrace( );}}System.out.print("A ");System.out.print("B ");System.out.print("C ");System.out.print("D ");System.out.print("\r\n");flag = 1;Printer.class.notify( );}}
}
4.3 练习
创建A1 A2 两个线程,分别打印1-10,11-20,保证A1执行完再 执行A2线程,A2执行完再执行A1
A1 —> 1
A2 —>11
A1 —> 2
A1 —>12
package com.qf.notify;/*** --- 天道酬勤 ---** @author QiuShiju* @desc*/
public class A1 extends Thread{@Overridepublic void run() {synchronized (TestA1A2.class) {for (int i = 1; i < 11; i++) {if (TestA1A2.flag != 1) {try {TestA1A2.class.wait();} catch (InterruptedException e) {e.printStackTrace( );}}System.out.println("A1 --> " + i);TestA1A2.flag = 2;TestA1A2.class.notify();}}}
}
class A2 extends Thread{@Overridepublic void run() {synchronized (TestA1A2.class) {for (int i = 11; i < 21; i++) {if (TestA1A2.flag != 2) {try {TestA1A2.class.wait();} catch (InterruptedException e) {e.printStackTrace( );}}System.out.println("A2 --> " + i);TestA1A2.flag = 1;TestA1A2.class.notify();}}}
}
class TestA1A2{static int flag = 1;public static void main(String[] args) {new A1().start();new A2().start();}
}
4.4 三个线程的通信
第一次
线程3抢到,判断标志是1,不是自己执行,改动标志为2,随机唤醒一条线程,但是此时所有线程都处于就绪状态,唤醒不唤醒无所谓…
第二次
假如线程2抢到,判断标志是2,自己执行,改动标志为3,随机唤醒一条线程,但是此时所有线程都处于就绪状态,唤醒不唤醒无所谓…
第三次
假如线程3抢到,判断标志是3,自己执行,改动标志为1,随机唤醒一条线程,但是此时所有线程都处于就绪状态,唤醒不唤醒无所谓…
第四次
假如这次又是线程3抢到,判断标志是1,不是自己执行,线程3陷入等待状态,让出资源
如果此时线程2抢到,判断标志是1,不是自己执行,线程2陷入等待状态,让出资源
此时只能线程1执行,判断标志是1,自己执行,改动标志为2,随机唤醒一条线程,如果唤醒是线程3,线程3从等待状态起来后通过while继续判断标志,发现不是自己,继续等待.此时只有线程1活跃,那么线程1执行,判断标志发现不是自己,陷入等待
解决方案: 全部唤醒 ,使用方法notifyAll(),唤醒所有处于等待状态的线程
package com.qf.notify;/*** --- 天道酬勤 ---** @author QiuShiju* @desc 打印机类*/
public class Printer2 {private int flag = 1;public void print1() {synchronized(Printer2.class) {// 改成while,让线程被唤醒后,继续判断// 如果是自己就执行,不是自己的标志就继续休眠while (flag != 1) {try {// 哪里等待,哪里起来继续执行Printer2.class.wait( );} catch (InterruptedException e) {e.printStackTrace( );}}System.out.print("1 ");System.out.print("2 ");System.out.print("3 ");System.out.print("4 ");System.out.print("\r\n");flag = 2;// 唤醒的是一条处于等待状态的线程(随机唤醒一条)// Printer2.class.notify( );// 唤醒所有等待的线程Printer2.class.notifyAll( );}}public void print2() {synchronized( Printer2.class) {while (flag != 2) {try {Printer2.class.wait( );} catch (InterruptedException e) {e.printStackTrace( );}}System.out.print("A ");System.out.print("B ");System.out.print("C ");System.out.print("D ");System.out.print("\r\n");flag = 3;Printer2.class.notifyAll( );}}public void print3() {synchronized( Printer2.class) {while (flag != 3) {try {Printer2.class.wait( );} catch (InterruptedException e) {e.printStackTrace( );}}System.out.print("一 ");System.out.print("二 ");System.out.print("三 ");System.out.print("四 ");System.out.print("\r\n");flag = 1;Printer2.class.notifyAll( );}}
}
第一次
线程3抢到,判断标志是1,不是自己执行,线程3陷入等待状态,让出资源
第二次
线程2抢到,判断标志是1,不是自己执行,线程2陷入等待状态,让出资源
第三次
线程1抢到,判断标志是1,自己执行,改动标志为2,随机唤醒一条线程
假如唤醒的是线程2,判断标志是2,自己执行,改动标志为3,唤醒线程3
但是假设线程2抢到,判断标志不是自己,线程2等待
假设线程1抢到,判断标志为3,不是自己,线程1也等待
线程3抢到资源开始执行,改动标志为1
随机唤醒一条线程,假如唤醒的线程2,现在判断标志是1,不是自己执行
线程2继续等待,现在活着的是线程3,抢到资源,判断标志不是自己,继续等待
4.5 总结
特殊的:
- wait和notify方法需要在同步方法或者同步代码块内执行
- wait会让当前线程进入等待状态,让出资源,其他线程可以执行
- wait和notify()方法谁调用? 当前锁对象是谁,就是谁调用该方法
问 wait和sleep有什么区别?
答:
wait是Object类的方法,sleep是Thread类方法
wait和sleep都可以让当前线程进入阻塞状态
但是wait阻塞当前线程,会让出系统资源,其他线程可执行;但是sleep阻塞当前线程,会持有锁不释放,其他线程无法执行
wait需要在同步方法或同步代码快中使用,但是sleep可以在同步或非同步都可以使用
问 为什么wait和notify方法要设计在Object类中?
答: 因为锁可以是任意对象,又因为wait和notify需要被 锁对象调用,那么锁对象是任意的,wait和notify方法也能被任意对象调用,所以就设计在Object类中,因为Object类是所有类的父类
五、生产者消费者
若干个生产者在生产产品,这些产品将提供给若干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置⼀个能存储多个产品的缓冲区,生产者将生产的产品放入缓冲区中,消费者从缓 冲区中取走产品进行消费,显然生产者和消费者之间必须保持同步,即不允许消费者到⼀个空的缓冲区中取产品,也不允许生产者向⼀个满的缓冲区中放入产品。
商品类 Phone
商店类 Shop
package com.qf.pc;/*** --- 天道酬勤 ---** @author QiuShiju* @desc*/
public class Phone {String name;public Phone(){}public Phone(String name){this.name = name;}
}
class Shop {Phone phone;// 进货(生产)public synchronized void putPhone(Phone phone) {if (this.phone != null) {// 有货,先等待,让别人消费try {this.wait();} catch (InterruptedException e) {e.printStackTrace( );}}// 进货this.phone = phone;System.out.println("进货,"+phone.name );// 通知消费this.notify();}// 售货(消费)public synchronized void sellPhone() {if (this.phone == null) {// 没有商品,不能消费,先等待生产try {this.wait();} catch (InterruptedException e) {e.printStackTrace( );}}// 消费System.out.println("消费,"+phone.name );this.phone = null;// 通知生产this.notify();}
}
class TestPC {public static void main(String[] args) {Shop shop = new Shop( );// 生产者线程new Thread(){@Overridepublic void run() {for (int i = 1; i < 6; i++) {shop.putPhone(new Phone("IPhone"+i));}}}.start();// 消费者线程new Thread(){@Overridepublic void run() {for (int i = 1; i < 11; i++) {shop.sellPhone();}}}.start();}
}
六、线程池
6.1 线程池概念
- 如果有非常多的任务需要非常多的线程来完成,每个线程的工作时间不长,就需要创建很多线程,工作完又立即销毁[
线程频繁创建和销毁线程
]- 频繁创建和销毁线程非常消费性能,那么线程池,就是可以创建一些线程,放在"池子"中,用的时候去池子取一个线程去使用,使用完再放回去,线程可以重用
- 线程池,底层其实就是集合队列,里面存储线程对象,用的时候去抽即可,就不要频繁创建线程了
使用线程池的好处是减少在创建和销毁线程上所花的时间以及系统资源的开销,解决资 源不足的问题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者 “过度切换”的问题 --> 摘自阿里官方手册
6.2 线程池原理
将任务(task)提交(submit/execute)给线程池(threadpool),由线程池分配线程,运行任务,任务结束后,线程重新放入线程池供后续线程使用
6.3 创建线程池的方式
使用线程池创建线程,执行任务
JDK提供了关于线程池的一些类和接口
- Executor: 线程池的根接口,通过execute(Runnable task) 执行任务
- ExecutorService: Executor的子接口,通过submit(Runnable task) 来提交任务,执行任务
ThreadPoolExecutor
: ExecutorService的子实现类,通过submit(Runnable task) 来提交任务,执行任务Executors
: 执行器类(线程池工厂类),通过该类来获得不同特点的线程池对象
类中有很多静态方法,直接调用就可以获得各种特点线程池对象
6.4 不同特点的线程池
通过Executors调用以下静态方法获得不同特点的线程池对象
方法 类型 解释 newFixedThreadPool 固定大小线程池 池中包含固定数目的线程,空闲线程一直保留。只有核心线程,线程数量固定,任务队列为LinkedBlockingQueue newCachedThreadPool 动态大小的线程池,原则上无上限 无核心线程,非核心线程数量无限,执行完闲置60s后回收,任务队列SynchronousQueue newScheduledThreadPool 可以执行定时任务的线程池 用于调度执行的固定线程池,执行定时或周期性任务。和弦线程数量固定,非核心线程数量无线,执行完闲置10ms后回收,任务队列为DelayedWorkQueue newSingleThreadExecutor 单线程线程池 只有一个线程的池,会顺序执行提交的任务,只有一个核心线程,无非核心线程,任务队列为LinkdBlockingQueue newSingleThreadScheduledExecutor 单线程定时任务线程池 newWorkStealingPool 1.8提供新的方式创建线程池
以上线程池操作在阿里java开发手册中是不建议用的…
说明:Executors 返回的线程池对象的弊端如下: 1)FixedThreadPool 和 SingleThreadPool: 允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。 2)CachedThreadPool 和 ScheduledThreadPool: 允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。 ----------------------- OOM 内存溢出,即系统资源耗尽
线程池执行任务时,可以采用两种方法:
execute(): 没有返回值,无法判断任务是否执行成功
submit():会返回Future对象,通过该对象判断任务是否执行成功
public static void main(String[] args) {// 固定大小线程池ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);for (int i = 0; i < 50; i++) {fixedThreadPool.execute(new Runnable( ) {@Overridepublic void run() {// System.out.println(Thread.currentThread().getName()+"干活" );}});}// 动态调整大小线程池ExecutorService fixedThreadPool2 = Executors.newCachedThreadPool();for (int i = 0; i < 50; i++) {fixedThreadPool2.execute(new Runnable( ) {@Overridepublic void run() {// System.out.println(Thread.currentThread().getName()+"干活" );}});}// 定时线程池ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(3);for (int i = 0; i < 5; i++) {scheduledExecutor.schedule(new Runnable( ) {@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"干活" );}},3, TimeUnit.SECONDS);}}
6.5 ThreadPoolExecutor[重要]
- ThreadPoolExecutor
很重要,有7个参数
参数名 解释 备注 int corePoolSize 指定线程池的线程数量(核心线程数) 不能小于0 int maximumPoolSize 指定线程池可支持的最大线程数 最大数量>=核心线程数 long keepAliveTime 指定临时线程的最大存活时间 不能小于0 TimeUnit unit 指定存活时间的单位(秒,分,时,天) 时间单位 BlockingQueue workQueue 指定任务队列 ThreadFactory threadFactory 指定哪个线程工厂创建线程 RejectedExecutionHandler handler 指定线程忙,任务队列满的时候新任务来了怎么办?拒绝策略
问: 什么是创建临时线程?
答: 新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建线程问:什么时候开始拒绝任务?
答:核心线程和临时线程都在忙,任务队列也满了,新的任务过来就会拒绝
LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(10);
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(5, 15, 10, TimeUnit.SECONDS, queue);for (int i = 0; i < 50; i++) {poolExecutor.submit(new Runnable( ) {@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"干活" );}});
}
今天这些都是会说,理解,能讲出来,不在于敲代码
相关文章:
day24_多线程进阶
今日内容 上课同步视频:CuteN饕餮的个人空间_哔哩哔哩_bilibili 同步笔记沐沐霸的博客_CSDN博客-Java2301 零、 复习昨日 一、作业 二、线程安全的集合 三、死锁 四、线程通信 五、生产者消费者 六、线程池 零、 复习昨日 创建线程的几种方式 1) 继承 2) 实现Runnable 3) calla…...
Qt实现系统桌面目录下文件搜索的GUI:功能一:文件查找与现实
⭐️我叫恒心,一名喜欢书写博客的研究生在读生。 原创不易~转载麻烦注明出处,并告知作者,谢谢!!! 这是一篇近期会不断更新的博客欧~~~ 有什么问题的小伙伴 欢迎留言提问欧。 功能点一:文件查找与…...
有关数据库的一级、二级、三级封锁协议
一级封锁协议 一级封锁协议是指,事务T在修改数据R之前必须先对其加X锁,直到事务结束才释放。事务结束包括正常结束(COMMIT)和非正常结束(ROLLBACK).一级封锁协议可防止丢失修改,并保证事务T是可恢复的。在…...
【Android Studio】【学习笔记】【2023春】
文章目录零、常用一、界面布局疑问&报错零、常用 一、界面布局 Android——六大基本布局总结/CSDN小马 同学 【Android】线性布局(LinearLayout)最全解析/CSDNTeacher.Hu 一个不错的计算器界面👇 Android Studio App LinearLayout多层…...
window.open()下载文件重命名/js下载文件重命名/js跨域下载文件重命名
普通文件下载 // 1 var fileUrl https://xxxx.docx; window.open(fileUrl"?attname文档.docx");// 2 var a document.createElement(a); a.href https://xxxx.docx; a.download 文档.docx; a.target "_blank"; a.click();以上方式 attname 和 a.down…...
zookeeper:简介及常用命令
目录 一、Zookeeper简介 二、Zookeeper服务端常用命令 1、启动ZooKeeper服务 2、查看ZooKeeper服务状态 3、停止ZooKeeper服务 4、重启ZooKeeper服务 三、Zookeeper客户端常用命令 1、连接ZooKeeper服务端 2、断开连接:quit 3、查看命令帮助:help…...
与流程挖掘布道者熵评科技孙一鸣博士共话流程挖掘市场的起源与前景 | 爱分析访谈
调研:李进宝 陈元新 撰写:李进宝 陈元新 随着数字化转型持续深入,国内企业流程挖掘需求初露端倪。流程挖掘是指通过采集和分析企业数据,以可视化流程图还原企业实际发生的业务流程,进而评估流程运行状况、诊断流程运…...
第十一届蓝桥杯省赛——2解密
题目:【问题描述】小明设计了一种文章加密的方法:对于每个字母 c,将它变成某个另外的字符 Tc。下表给出了字符变换的规则:字母cTc字母cTc字母cTc字母cTcaynlAYNLbxogBXOGcmpoCMPOddquDDQUearfEARFfcssFCSSgitzGITZhkupHKUPinvwINV…...
ChatGPT解答:PYQT5 美化各种控件的方案和实例
ChatGPT解答:PYQT5 美化各种控件的方案和实例 修改按钮样式 button QPushButton(按钮, self) button.setStyleSheet(QPushButton{background-color: red; border-radius: 5px;})修改标签样式 label QLabel(标签, self) label.setStyleSheet(QLabel{color: blue; …...
js实现翻盘抽奖
<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>礼物编辑</title><style>* {margin: 0;padding: 0;box-sizing: border-box;list-style-type: none;text-decoration: none;}.container {d…...
Qt QtCreator 安卓开发环境搭建
踩坑 我的qt是使用在线安装工具安装的,Qt版本使用的是5.15.2,QtCreator版本9.0.2 在网上很多教程都是如下步骤 1.安装qt 2.安装jdk 3.安装android-sdk 4.安装android-ndk 5.配置android设置 例如: https://blog.csdn.net/weixin_51363326/…...
Flutter知识点(二)处理Json
flutter不支持反射,所以本来很简单的事情,一下子变复杂了。当然官方也提供了一些工具来方便开发者。 由于Dart的map和array的数据结构和json一样,所以在flutter中,变成了json string与Map,array之间的砖换。 &#x…...
基本概念简介(码率,FPS(帧数),分辨率,RTMP协议)等的介绍
基本概念 为了了解视频的码率、帧率、分辨率。我们先来看看视频编码的基本原理:视频图像数据有极强的相关性,也就是说有大量的冗余信息。压缩技术就是将数据中的冗余信息去掉(去除数据之间的相关性),压缩技术包含帧内图像数据压缩技术、帧间图像数据压缩技术和熵编码压缩技…...
黑盒测试重点复习内容
黑盒测试一、等价类划分边界值分析法二、判定表法一、等价类划分边界值分析法 对于各种输入或者输出,必须考虑等价类和边界值,并补充一些特殊值,如空值、空格、0、异常格式等特殊值。 基本概念: 有效等价类:满足需求…...
Python每日一练(20230303)
1. 两数之和 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。 你可以按任意顺…...
基于Cortex-M7内核STM32F767NIH6,STM32F767VGT6,STM32F767VIT6嵌入式技术资料
STM32F7 32 位 MCUFPU 基于高性能的 ARMCortex-M7 32 位 RISC 内核,工作频率高达 216MHz。Cortex-M7 内核具有单浮点单元(SFPU)精度,支持所有 ARM 单精度数据处理指令与数据类型。同时执行全套 DSP 指令和存储保护单元(MPU)&#…...
Nginx SSL证书A+之路
问题 myssl是常见的SSL/TLS在线免费检测网站。期望能够达到A级别。 步骤 nignx worker_processes auto;http {ssl_session_cache shared:SSL:10m;ssl_session_timeout 10m;server {listen 443 ssl;server_name xxxx.xxxx.com;keepalive_timeout 70;ssl_certific…...
周期性温度和压力波的PID自动控制解决方法
摘要:目前各种PID控制器仪表常用于简单的设定点(Set Point)和斜坡(Ramp)程序控制,但对于复杂的正弦波等周期性变量的控制则无能为力。为了采用标准PID控制器便捷和低成本的实现对正弦波等周期性变量的自动控…...
从头开始搭建一个SpringBoot项目--SpringBoot文件的上传与下载
从头开始搭建一个SpringBoot项目--SpringBoot文件的上传前言流程分析代码结构代码详情UploadFileInfo.classUploadController.classUploadDao.classUploadDao.xmlUploadServices.classUploadServicesImpl.class测试下载示例前言 文件的上传和下载是很多系统必备的功能…...
It做形式主语和宾语
主谓宾,主宾能被名词性的sth,替换,如动名词,不定式,从句等等 而且,不能出现前面或者中间,很长,一大推的在开头或者中间,就产生了it做形式主宾。 一、It用作形式主语当不…...
做测试一定要知道的——软件测试流程和测试规范标准文档
目录 1、目的 2、工作范围 3、工作职责 4、测试的流程 5、测试准备阶段 6、测试方法制定阶段 7、测试执行阶段 8、bug管理 9、标准文档 总结感谢每一个认真阅读我文章的人!!! 重点:配套学习资料和视频教学 1、目的 通…...
Linux下将一个文件压缩分包成多个小文件
压缩分包 将文件test分包压缩成1G 的文件: tar czf - 文件名字 | split -b 10 - 文件名.tar.gz解压 将第一步分拆的多个包解压: cat 文件名.tar.gz* | tar -xzv...
分享5款用了一段时间,个人觉得非常nice的软件
大家在使用Windows办公、学习的时候,有没有觉得自己的电脑差了点意思?比如:电脑桌面上太杂乱、装满了各类五花八门的软件、桌面壁纸不美观等。今天,给大家分享五款个人用了段时间后,觉得非常nice的软件。 1.鼠标可视化…...
搜广推 Product-based Neural Networks (PNN) - 改进特征交叉的方式
😄 PNN:2016年上海交通大学提出。 文章目录 1、PNN1.1、原理1.2、创新点:product层1.3、product层z部分的输出:l~z~ 的计算方式:1.4、product层z部分的输出:l~p~ 的计算方式:1.4.1、IPNN1.4.2、OPNN1.5、优点1.6、缺点Reference1、PNN PNN:Product-based Neural Netwo…...
IDEA2022 配置spark开发环境
本人强烈建议在 linux环境下 学习 spark!!! Introduction Apache Spark是一个快速且通用的分布式计算引擎,可以在大规模数据集上进行高效的数据处理,包括数据转换、数据清洗、机器学习等。在本文中,我们将…...
趣味答题竞赛小程序开发功能的详细介绍
随着人们对知识学习的要求越来越高,答题已经成为了一项重要的学习和考核方式。而为了让答题变得更加有趣和富有挑战性,我们推出了趣味答题竞赛小程序。下面,我们将详细介绍这个小程序的开发功能。 1.个人淘汰赛 在个人淘汰赛中,…...
【独家】华为OD机试提供C语言题解 - 获取最大软件版本号
最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧文章目录 最近更新的博客使用说明获取…...
k8s编程operator实战之云编码平台——⑤项目完成、部署
文章目录1、效果展示2、保存用户状态和访问用户服务实现方案2.1 如何保存用户的状态2.1.1 解决保留安装的插件问题2.2 如何访问到用户在工作空间中启动的http服务2.2.1 code-server如何帮我们实现了用户程序的代理3、Operator功能实现3.1 使用KubeBuilder创建项目3.1.1 完善kin…...
C语言杂记(指针篇)
指针篇 指针就是地址,地址就是指针 指针变量就是存放地址的变量 *号只有定义的时候表示定义指针变量,其他表示从地址里面取内容 通过指针的方法使main函数中的data1和data2发生数据交换。 #include <stdio.h> void chang_data(int *data1,int *da…...
ES window 系统环境下连接问题
环境问题:(我采用的版本是 elasticsearch-7.9.3)注意 开始修正之前的配置:前提:elasticsearch.yml增加或者修正一下配置:xpack.security.enabled: truexpack.license.self_generated.type: basicxpack.secu…...
wordpress tob8.0/谷歌sem推广
一 问题描述 问题描述前,请允许我,吐槽一下,这个问题困扰了一天,下面在业务层下的代码中,cache注解标注了value的名称,但是没有设置key,且传递的参数为 CrawlRecordParamVo crawlRecordParamV…...
专业的模板建站企业/seo推广公司排名
Bootstrap资源: 兼容性不错的简洁BuiBootstrap后台管理系统模板 [url]http://www.js-css.cn/divcss/admin/bui-bootstrap[/url], 下载 [url]http://www.js-css.cn/a/css/template/admin/2013/1108/1023.html[/url] 值得收藏!4个Bootstrap3开发的后台管理模板 [url]h…...
做微网站用哪个平台/seo免费优化网站
2019独角兽企业重金招聘Python工程师标准>>> 考虑提供一种网络功能, 教师在自己机器上面画图, 能够显示给学生; 或获取学生的图形, 并在其 基础上修改绘制, 学生能看到画图过程. 设学生机器为S, 教师机器为T, 服务器为V. 一般思路: S,T 通过服务器V连接, 通过V传输…...
成都市最新疫情最新消息/优化软件下载
/**abstruct 抽象类 中可以定义方法体,也可以不定义方法体。未定义方法体的需要用abstruct定义为抽象方法,则子类必须去实现抽象类的抽象方法。不可被实例化,没有构造函数。interface 接口 中不可以定义方法体,子类实现接口时&…...
吉林省网站建设行业需求分析/十大引擎网址
题目:写一个函数返回参数二进制中 1 的个数比如: 15 0000 1111 4 个 1程序原型:int count_one_bits(unsigned int value){// 返回 1的位数 }解题思路:首先写出这个数字的二进制序列并且定义一个计数器,由于数字在计算机…...
wordpress 内页插件/搭建网站
原文出处: 微软互联网开发支持 Visual Studio 是一个强大的调试工具,里面很多隐藏功能少有人问津,但是在特定场景可以节省你很多时间,本文主要介绍一些Visual Studio调试相关的隐藏功能,欢迎大家补充。 运行到光标(R…...