并发编程---java锁
java锁
- 一 多线程锁synchronized案例分析
- 1.1synchronized介绍
- 1.2 synchronized案例分析
- 1.2.1.标准访问,请问先打印邮件还是短信?
- 1.2.2.邮件⽅法暂停4秒钟,请问先打印邮件还是短信?
- 分析
- 1.2.3.新增⼀个普通⽅法hello(),请问先打印邮件还是hello?
- 1.2.4.两部⼿机,请问先打印邮件还是短信?
- 1.2.5.两个静态同步⽅法,同⼀部⼿机,请问先打印邮件还是短信?
- 1.2.6.两个静态同步⽅法,2部⼿机,请问先打印邮件还是短信?
- 1.2.7.1个普通同步⽅法,1个静态同步⽅法,1部⼿机,请问先打印邮件还是短信?
- 1.2.8.1个普通同步⽅法,1个静态同步⽅法,2部⼿机,请问先打印邮件还有短信?
- 1.2.8 总结
- 二⼈⼯窗⼝排队购票(回顾)
- 三 公平锁⾮公平锁 (⽕⻋站⼈⼯窗⼝排队购票)
- 四 可重⼊锁/递归锁
- 锁的配对
- 五 ⾃旋锁
- 六 读写锁/独占/共享
一 多线程锁synchronized案例分析
1.1synchronized介绍
关键字synchronized可以保证在同一时刻,只有一个线程可以执行某个方法或某个代码块,同时synchronized可以保证一个线程的变化可见(可见性),即可以代替volatile使用方法
1.普通同步方法(实例方法),锁是当前实例对象 ,进入同步代码前要获得当前实例的锁
2.静态同步方法,锁是当前类的class对象 ,进入同步代码前要获得当前类对象的锁
3.同步方法块,锁是括号里面的对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁
1.2 synchronized案例分析
使用8个案例来详细说明synchronized的加锁用法:
1.标准访问,请问先打印邮件还是短信?
2.邮件⽅法暂停4秒钟,请问先打印邮件还是短信?
3.新增⼀个普通⽅法hello(),请问先打印邮件还是hello?
4.两部⼿机,请问先打印邮件还是短信?
5.两个静态同步⽅法,同⼀部⼿机,请问先打印邮件还是短信?
6.两个静态同步⽅法,2部⼿机,请问先打印邮件还是短信?
7.1个普通同步⽅法,1个静态同步⽅法,1部⼿机,请问先打印邮件还是短信?
8.1个普通同步⽅法,1个静态同步⽅法,2部⼿机,请问先打印邮件还有短信?
1.2.1.标准访问,请问先打印邮件还是短信?
答案:邮件
class Phone {public synchronized void sendEmail() {System.out.println("==========sendEmail");}public synchronized void sendMessage() {System.out.println("======sendMessage");}
}public class LockDemo {public static void main(String[] args) {Phone phone = new Phone();new Thread(() -> {phone.sendEmail();}, "t1").start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {phone.sendMessage();}, "t2").start();//==========sendEmail//======sendMessage}
}
1.2.2.邮件⽅法暂停4秒钟,请问先打印邮件还是短信?
答案:邮件
//2. 邮件方法暂停4秒钟,请问先打印邮件还是短信? 邮件
class Phone {public synchronized void sendEmail() {try {TimeUnit.SECONDS.sleep(4);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("==========sendEmail");}public synchronized void sendMessage() {System.out.println("======sendMessage");}}public class LockDemo {public static void main(String[] args) {Phone phone = new Phone();new Thread(() -> {phone.sendEmail();}, "t1").start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {phone.sendMessage();}, "t2").start();//==========sendEmail//======sendMessage}
}
分析
普通同步方法(实例方法),锁是当前实例对象 ,进入同步代码前要获得当前实例的锁
⼀个对象⾥⾯如果有多个synchronized⽅法,某⼀个时刻内,只要⼀个线程去调⽤其中的⼀个synchronized⽅法了,其他的线程都只能等待。换句话说,某⼀个时刻内,只能有唯⼀⼀个线程去访问这些 synchronized⽅法,锁的是当前对象this(new 的这个phone),被锁定后,其他的线程都不能进⼊到当前对象的其他的synchronized⽅法。

1.2.3.新增⼀个普通⽅法hello(),请问先打印邮件还是hello?
答案:hello
加个普通⽅法后发现和同步锁⽆关

//3. 新增一个普通方法hello(),请问先打印邮件还是hello?
class Phone {public synchronized void sendEmail() {try {TimeUnit.SECONDS.sleep(4);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("==========sendEmail");}public synchronized void sendMessage() {System.out.println("======sendMessage");}public void hello() {System.out.println("sayHello");}
}public class LockDemo {public static void main(String[] args) {Phone phone = new Phone();new Thread(() -> {phone.sendEmail();}, "t1").start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {phone.sendMessage();}, "t2").start();new Thread(() -> {phone.hello();}, "t3").start();//sayHello//==========sendEmail//======sendMessage}
}
1.2.4.两部⼿机,请问先打印邮件还是短信?
答案:邮件
分析:换成两个对象后,不是同⼀把锁了,情况⽴刻变化
//4. 两部手机,请问先打印邮件还是短信?
class Phone {public synchronized void sendEmail() {try {TimeUnit.SECONDS.sleep(4);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("==========sendEmail");}public synchronized void sendMessage() {System.out.println("======sendMessage");}public void hello() {System.out.println("sayHello");}
}public class LockDemo {public static void main(String[] args) {Phone phone = new Phone();Phone phone2 = new Phone();new Thread(() -> {phone.sendEmail();}, "t1").start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {phone2.sendMessage();}, "t2").start();//======sendMessage//==========sendEmail}
}
1.2.5.两个静态同步⽅法,同⼀部⼿机,请问先打印邮件还是短信?
答案:邮件
分析:见 1.2.6
//5. 两个静态同步方法,同一部手机,请问先打印邮件还是短信?
class Phone {public static synchronized void sendEmail() {try {TimeUnit.SECONDS.sleep(4);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("==========sendEmail");}public static synchronized void sendMessage() {System.out.println("======sendMessage");}public void hello() {System.out.println("sayHello");}
}public class LockDemo {public static void main(String[] args) {Phone phone = new Phone();new Thread(() -> {phone.sendEmail();}, "t1").start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {phone.sendMessage();}, "t2").start();//==========sendEmail//======sendMessage}
}
1.2.6.两个静态同步⽅法,2部⼿机,请问先打印邮件还是短信?
答案: 邮件
分析: 静态同步方法,锁是当前类的class对象 ,进入同步代码前要获得当前类对象的锁
全局锁

//6. 两个静态同步方法,2部手机,请问先打印邮件还是短信?
class Phone {public static synchronized void sendEmail() {try {TimeUnit.SECONDS.sleep(4);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("==========sendEmail");}public static synchronized void sendMessage() {System.out.println("======sendMessage");}public void hello() {System.out.println("sayHello");}
}public class LockDemo {public static void main(String[] args) {Phone phone = new Phone();Phone phone2 = new Phone();new Thread(() -> {phone.sendEmail();}, "t1").start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {phone2.sendMessage();}, "t2").start();//==========sendEmail//======sendMessage}
}
1.2.7.1个普通同步⽅法,1个静态同步⽅法,1部⼿机,请问先打印邮件还是短信?
答案: 短信
分析:

//7. 1个普通同步方法,1个静态同步方法,1部手机,请问先打印邮件还是短信?
class Phone {public synchronized void sendEmail() {try {TimeUnit.SECONDS.sleep(4);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("==========sendEmail");}public static synchronized void sendMessage() {System.out.println("======sendMessage");}public void hello() {System.out.println("sayHello");}
}public class LockDemo {public static void main(String[] args) {Phone phone = new Phone();new Thread(() -> {phone.sendEmail();}, "t1").start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {phone.sendMessage();}, "t2").start();//======sendMessage//==========sendEmail}
}
1.2.8.1个普通同步⽅法,1个静态同步⽅法,2部⼿机,请问先打印邮件还有短信?
答案: 短信
分析:

1.2.8 总结
(1)当⼀个线程试图访问同步代码块时,它⾸先必须得到锁,退出或抛出异常时必须释放锁。 也就是说如果⼀个实例对象的普通同步⽅法获取锁后,该实例对象的其他普通同步⽅法必须等待获取锁的⽅法释放锁后才能获取锁,可是别的实例对象的普通同步⽅法因为跟该实例对象的普通同步⽅法⽤的是不同的锁,所以⽆需等待该实例对象已获取锁的普通同步⽅法释放锁就可以获取他们⾃⼰的锁。
(2)所有的静态同步⽅法⽤的也是同⼀把锁–类对象本身, 这两把锁(this/class)是两个不同的对象,所以静态同步⽅法与⾮静态同步⽅法之间是 不会有静态条件的。 但是⼀旦⼀个静态同步⽅法获取锁后,其他的静态同步⽅法都必须等待该⽅法释放锁后才能获取锁,⽽不管是同⼀个实例对象的静态同步⽅法之间,还是不同的实例对象的静态同步⽅法之间,只要它们同⼀个类的实例对象
二⼈⼯窗⼝排队购票(回顾)
题目:三个售票员 卖出 30张票
多个线程共抢一个资源
/*** 题目:三个售票员 卖出 30张票**/
class Ticket{//资源类//票private int number = 30;public synchronized void saleTicket(){if (number > 0) {System.out.println(Thread.currentThread().getName()+"\t卖出第:"+(number--)+"\t还剩下:"+number);}}}public class SaleTicketDemo {public static void main(String[] args) {Ticket ticket = new Ticket();new Thread(()->{ for (int i = 1; i <= 30 ; i++) ticket.saleTicket(); }, "A").start();new Thread(()->{ for (int i = 1; i <= 30 ; i++) ticket.saleTicket(); }, "B").start();new Thread(()->{ for (int i = 1; i <= 30 ; i++) ticket.saleTicket(); }, "C").start();}
}

我们用synchronized同步代码块的方式来解决。随着juc并发编程。我们有更加轻量级的锁方式来解决问题。
三 公平锁⾮公平锁 (⽕⻋站⼈⼯窗⼝排队购票)
lcok锁
Lock lock = new ReentrantLock();



概念:
公平锁,就是多个线程按照申请锁的顺序来获取锁,类似排队,先到先得。
⾮公平锁,则是多个线程抢夺锁,会导致优先级反转或饥饿现象。
区别:
- 公平锁在获取锁时先查看此锁维护的等待队列,为空或者当前线程是等待队列的队⾸,则直接占有锁,否则插⼊到等待队列,FIFO原则。
- ⾮公平锁⽐较粗鲁,上来直接先尝试占有锁,失败则采⽤公平锁⽅式。⾮公平锁的优点是吞吐量⽐公平锁更⼤。
synchronized和 juc.ReentrantLock默认都是⾮公平锁。 ReentrantLock在构造的时候传⼊ true 则是公平锁。
四 可重⼊锁/递归锁

可重⼊锁⼜叫递归锁,指的同⼀个线程在外层⽅法获得锁时,进⼊内层⽅法会⾃动获取锁。也就是说,线程可以进⼊任何⼀个它已经拥有锁的代码块。
⽐如method01⽅法⾥⾯有method02⽅法,两个⽅法都有同⼀把锁,得到了method01的锁。就⾃动得到了method02的锁,就像有了家⻔的锁,厕所、书房、厨房就为你敞开了⼀样。可重⼊锁可以避免死锁的问题。

/*** 可重入锁/递归锁*/class PhonePlus implements Runnable{//Synchronized Testpublic synchronized void sendEmail(){System.out.println(Thread.currentThread().getName()+"\t"+"sendEmail");sendSMS();}public synchronized void sendSMS(){System.out.println(Thread.currentThread().getName()+"\t"+"sendSMS");}//ReenTrantLock TestLock lock = new ReentrantLock();public void method1(){lock.lock();try {System.out.println(Thread.currentThread().getName()+"\t"+"method1");method2();} finally {lock.unlock();}}public void method2() {lock.lock();try {System.out.println(Thread.currentThread().getName()+"\t"+"method2");} finally {lock.unlock();}}@Overridepublic void run() {method1();}
}public class ReentrantLockDemo {public static void main(String[] args) {PhonePlus phonePlus = new PhonePlus();new Thread(()->{phonePlus.sendEmail();}, "t1").start();new Thread(()->{phonePlus.sendEmail();}, "t2").start();Thread t3 = new Thread(phonePlus);Thread t4 = new Thread(phonePlus);t3.start();t4.start();}
}
锁的配对
锁之间要配对,加了⼏把锁,最后就得解开⼏把锁,下⾯的代码编译和运⾏都没有任何问题。但锁的数量不匹配会导致死循环。
lock.lock();
lock.lock();
try{someAction();
}finally{lock.unlock();
}
五 ⾃旋锁
所谓⾃旋锁,就是尝试获取锁的线程不会⽴即阻塞,⽽是采⽤循环的⽅式去尝试获取。⾃⼰在那⼉⼀直循环获取,就像“⾃旋”⼀样。这样的好处是减少线程切换的上下⽂开销,缺点是会消耗CPU。CAS底层的 getAndAddInt就是⾃旋锁思想。
//跟CAS类似,⼀直循环⽐较。
while (!atomicReference.compareAndSet(null, thread)) { }

/*** 题目:实现一个自旋锁* 自旋锁好处:循环比较获取直到成功为止,没有类似wait的阻塞。* <p>* 通过CAS操作完成自旋锁,A线程先进来调用myLock方法自己持有锁5秒钟,* B随后进来后发现当前有线程持有锁,不是null,所以只能通过自选等待,直到A释放锁后B随后抢到。*/
public class SpinLockDemo {//原子引用(线程)AtomicReference<Thread> atomicReference = new AtomicReference<>(); //Thread ==> null//获取锁public void myLock() {Thread currentThread = Thread.currentThread();System.out.println(Thread.currentThread().getName() + "\t com in...");while (!atomicReference.compareAndSet(null, currentThread)) {}}//释放锁public void myUnLock() {Thread currentThread = Thread.currentThread();atomicReference.compareAndSet(currentThread, null);System.out.println(Thread.currentThread().getName() + "\t unlock....");}public static void main(String[] args) {SpinLockDemo spinLockDemo = new SpinLockDemo();new Thread(() -> {spinLockDemo.myLock();try {TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}spinLockDemo.myUnLock();}, "AA").start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {spinLockDemo.myLock();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}spinLockDemo.myUnLock();}, "BB").start();}
}
结果

过程分析

六 读写锁/独占/共享
读锁是共享的,写锁是独占的。 juc.ReentrantLock和 synchronized都是独占锁,独占锁就是⼀个锁只能被⼀个线程所持有。有的时候,需要读写分离,那么就要引⼊读写锁,即 juc.ReentrantReadWriteLock。
独占锁:指该锁⼀次只能被⼀个线程所持有。对
ReentrantLock和Synchronized⽽⾔都是独占锁
共享锁:指该锁可被多个线程所持有
对ReenntrantReadWriteLock其读锁是共享锁,其写锁是独占锁。
读锁的共享锁可保证并发读是⾮常⾼效的,读写、写读、写写的过程是互斥的。
⽐如缓存,就需要读写锁来控制。缓存就是⼀个键值对,以下Demo模拟了缓存的读写操作,读的 get ⽅法使⽤了 ReentrantReadWriteLock.ReadLock(),写的 put⽅法使⽤了ReentrantReadWriteLock.WriteLock()。这样避免了写被打断,实现了多个线程同时读。
相关文章:
并发编程---java锁
java锁一 多线程锁synchronized案例分析1.1synchronized介绍1.2 synchronized案例分析1.2.1.标准访问,请问先打印邮件还是短信?1.2.2.邮件⽅法暂停4秒钟,请问先打印邮件还是短信?分析1.2.3.新增⼀个普通⽅法hello(&…...
品牌营销 | 学习如何最大限度地发挥品牌营销的作用
您是否想过如何最大限度地发挥品牌营销的潜力?这是一项艰巨的挑战,通过了解品牌营销的基本组成部分,您可以成功地推广您的品牌。 (图源:Pixabay) 品牌营销的基本组成部分 你需要做什么来发展稳固的品牌&am…...
Linux驱动的同步阻塞和同步非阻塞
在字符设备驱动中,若要求应用与驱动同步,则在驱动程序中可以根据情况实现为阻塞或非阻塞一、同步阻塞这种操作会阻塞应用程序直到设备完成read/write操作或者返回一个错误码。在应用程序阻塞这段时间,程序所代表的进程并不消耗CPU的时间&…...
LearnOpenGL-光照-5.投光物
本人刚学OpenGL不久且自学,文中定有代码、术语等错误,欢迎指正 我写的项目地址:https://github.com/liujianjie/LearnOpenGLProject 文章目录投光物平行光点光源聚光不平滑的例子平滑例子投光物 前面几节使用的光照都来自于空间中的一个点 即…...
【C语言】每日刷题 —— 牛客语法篇(1)
前言 大家好,今天带来一篇新的专栏c_牛客,不出意外的话每天更新十道题,难度也是从易到难,自己复习的同时也希望能帮助到大家,题目答案会根据我所学到的知识提供最优解。 🏡个人主页:悲伤的猪大…...
【深度学习】Subword Tokenization算法
在自然语言处理中,面临的首要问题是如何让模型认识我们的文本信息,词,是自然语言处理中基本单位,神经网络模型的训练和预测都需要借助词表来对句子进行表示。 1.构建词表的传统方法 在字词模型问世之前,做自然语言处理…...
五分钟了解支付、交易、清算、银行等专业名词的含义?
五分钟了解支付、交易、清算、银行等专业名词的含义?1. 支付类名词01 支付应用02 支付场景03 交易类型04 支付类型(按通道类型)05 支付类型(按业务双方类型)06 支付方式07 支付产品08 收银台类型09 支付通道10 通道类型…...
4个工具,让 ChatGPT 如虎添翼!
LightGBM中文文档 机器学习统计学,476页 机器学习圣经PRML中文版...
初识PO、VO、DAO、BO、DTO、POJO时
PO、VO、DAO、BO、DTO、POJO 区别分层领域模型规约DO(Data Object)DTO(Data Transfer Object)BO(Business Object)AO(ApplicationObject)VO(View Object)Query领域模型命名规约:一、PO :(persistant object ),持久对象二、VO :(value object) ࿰…...
[2.2.4]进程管理——FCFS、SJF、HRRN调度算法
文章目录第二章 进程管理FCFS、SJF、HRRN调度算法(一)先来先服务(FCFS, First Come First Serve)(二)短作业优先(SJF, Shortest Job First)对FCFS和SJF两种算法的思考(三…...
【代码随想录Day55】动态规划
583 两个字符串的删除操作 https://leetcode.cn/problems/delete-operation-for-two-strings/72 编辑距离https://leetcode.cn/problems/edit-distance/...
Java开发 - 消息队列前瞻
前言 学完了Redis,那你一定不能错过消息队列,要说他俩之间的关联?关联是有的,但也不见得很大,只是他们都是大数据领域常用的一种工具,一种用来提高程序运行效率的工具。常见于高并发,大数据&am…...
MySQL连接IDEA详细教程
使用IDEA的时候,需要连接Database,连接时遇到了一些小问题,下面记录一下操作流程以及遇到的问题的解决方法。 目录 MySQL连接IDEA详细教程 MySQL连接IDEA详细教程 打开idea,点击右侧的 Database 或者 选择 View --> Tool Wind…...
线程(操作系统408)
基本概念 我们说引入进程的目的是更好的使用多道程序并发执行,提高资源的利用率和系统吞吐量;而引入线程的目的则是减小程序在并发执行的时候所付出的时间开销,提高操作系统的并发性能。 线程可以理解成"轻量级进程",…...
功耗降低99%,Panamorph超清VR光学架构解析
近期,投影仪变形镜头厂商Panamorph获得新型VR显示技术专利(US11493773B2),该专利方案采用了紧凑的结构,结合了Pancake透镜和光波导显示模组,宣称比传统VR方案的功耗、发热减少99%以上,可显著提高…...
【数据结构】带你深入理解栈
一. 栈的基本概念💫栈是一种特殊的线性表。其只允许在固定的一端进行插入和删除元素的操作,进行数据的插入和删除的一端称作栈顶,另外一端称作栈底。栈不支持随机访问,栈的数据元素遵循后进先出的原则,即LIFOÿ…...
认识CSS之如何提高写前端代码的效率
🌟所属专栏:前端只因变凤凰之路🐔作者简介:rchjr——五带信管菜只因一枚😮前言:该系列将持续更新前端的相关学习笔记,欢迎和我一样的小白订阅,一起学习共同进步~👉文章简…...
Vue中watch和computed
首先这里进行声明,这个讲的是vue2的内容,在vue3发生了什么变动与此无关 这里是官网: https://v2.cn.vuejs.org/v2/guide/installation.html computed > 计算属性 watch > 侦听器(也叫监视器) 其区别如下&…...
华为鲲鹏+银河麒麟v10 安装 docker-ce
设备:硬件:仅有ARM处理器,无GPU和NPU,操作系统麒麟银河V10,Kunpeng-920 #######参考原链接######### 华为鲲鹏银河麒麟v10 安装 docker-ce 踩坑 - akiyaの博客 在 arm64(aarch64) 架构服务器上基于国产化操作系统安…...
Lambda,Stream,响应式编程从入门到放弃
Lambda表达式 Java8新引入的语法糖 Lambda表达式*(关于lambda表达式是否属于语法糖存在很多争议,有人说他并不是语法糖,这里我们不纠结于字面表述)*。Lambda表达式是一种用于取代匿名类,把函数行为表述为函数式编程风…...
3步解决HEIC预览难题:面向Windows用户的高效缩略图工具
3步解决HEIC预览难题:面向Windows用户的高效缩略图工具 【免费下载链接】windows-heic-thumbnails Enable Windows Explorer to display thumbnails for HEIC files 项目地址: https://gitcode.com/gh_mirrors/wi/windows-heic-thumbnails 在数字影像管理中&…...
ZeroOmega多代理管理功能全解析:实现智能网络访问控制的核心方案
ZeroOmega多代理管理功能全解析:实现智能网络访问控制的核心方案 【免费下载链接】ZeroOmega Manage and switch between multiple proxies quickly & easily. 项目地址: https://gitcode.com/gh_mirrors/ze/ZeroOmega ZeroOmega作为一款开源的多代理管理…...
Qwerty Learner 数据持久化架构深度解析:IndexedDB 异步存储方案技术实现
Qwerty Learner 数据持久化架构深度解析:IndexedDB 异步存储方案技术实现 【免费下载链接】qwerty-learner 项目地址: https://gitcode.com/GitHub_Trending/qw/qwerty-learner 在英语单词记忆与打字训练应用中,数据持久化架构直接影响学习体验的…...
nanomsg性能基准测试终极指南:不同消息大小下的吞吐量对比分析
nanomsg性能基准测试终极指南:不同消息大小下的吞吐量对比分析 【免费下载链接】nanomsg nanomsg library 项目地址: https://gitcode.com/gh_mirrors/na/nanomsg nanomsg是一个轻量级、高性能的消息传递库,专为解决常见的通信模式而设计。作为na…...
PlayCover终极指南:三步在Mac上畅玩iOS游戏与应用
PlayCover终极指南:三步在Mac上畅玩iOS游戏与应用 【免费下载链接】PlayCover Community fork of PlayCover 项目地址: https://gitcode.com/gh_mirrors/pl/PlayCover 还在为心爱的iOS游戏无法在Mac上体验而烦恼吗?PlayCover为你打开了一扇全新的…...
League-Toolkit英雄联盟工具集启动故障解决方案
League-Toolkit英雄联盟工具集启动故障解决方案 【免费下载链接】League-Toolkit 兴趣使然的、简单易用的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit League-Toolkit作为一款基于LCU A…...
ONLYOFFICE Docs与Nextcloud Calendar集成:打造高效私有云日程协作平台
ONLYOFFICE Docs与Nextcloud Calendar集成:打造高效私有云日程协作平台 【免费下载链接】DocumentServer ONLYOFFICE Docs is a free collaborative online office suite comprising viewers and editors for texts, spreadsheets and presentations, forms and PDF…...
开源项目主题系统的3大核心机制深度解析:从CSS变量到动态切换的完整实现方案
开源项目主题系统的3大核心机制深度解析:从CSS变量到动态切换的完整实现方案 【免费下载链接】vue-vben-admin vbenjs/vue-vben-admin: 是一个基于 Vue.js 和 Element UI 的后台管理系统,支持多种数据源和插件扩展。该项目提供了一个完整的后台管理系统&…...
带标注的交通工具分类数据集,17334张原始图片,识别率92.4%,可识别汽车,公共汽车,自行车,摩托车,支持yolo,coco json,pascal voc xml格式
带标注的交通工具分类数据集,17334张原始图片,识别率92.4%,可识别汽车,公共汽车,自行车,摩托车,支持yolo,coco json,pascal voc xml格式 模型训练指标参数: …...
关于腾讯广告算法大赛2025项目分析1 - dataset.py
把原始 jsonl 用户行为序列,转成模型能直接吃的张量tensor和特征字典 一、整体定位 MyDataset 读取训练数据,产出: 用户序列 seq正样本 pos负样本 negtoken 类型各类特征时间特征相关原始时间戳 MyTestDataset 读取测试/推理数据,产出 用户序…...
