java并发编程笔记(三)--管程(二)

2023-11-17

习题:卖票

请改正:

public class ExerciseSell {
 public static void main(String[] args) {
 
 //2000张票
 TicketWindow ticketWindow = new TicketWindow(2000);
 //买票的线程
 List<Thread> list = new ArrayList<>();
     
 // 用来存储买出去多少张票
 List<Integer> sellCount = new Vector<>();
     
 for (int i = 0; i < 2000; i++) {
     
 Thread t = new Thread(() -> {
     
 // 分析这里的竞态条件
 int count = ticketWindow.sell(randomAmount());
     
 sellCount.add(count);
 });
     
 list.add(t);
 t.start();
 }
 
 list.forEach((t) -> {
 try {
 t.join();
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 });
     
 // 买出去的票求和
 log.debug("selled count:{}",sellCount.stream().mapToInt(c -> c).sum());
 // 剩余票数
 log.debug("remainder count:{}", ticketWindow.getCount());
 }
    
 // Random 为线程安全
 static Random random = new Random();
 // 随机 1~5
 public static int randomAmount() {
 return random.nextInt(5) + 1;
 }
    
}

class TicketWindow {
 private int count;
    
 public TicketWindow(int count) {
 this.count = count;
 }
    
 public int getCount() {
 return count;
 }
    
 public int sell(int amount) {

if (this.count >= amount) {
 this.count -= amount;
 return amount;
}
     else {
 return 0;
 }
 }
}

解决方法:

public synchronized int getCount() {
 return count; }
    
public int sell(int amount) {

if (this.count >= amount) {
 this.count -= amount;
 return amount;
}
 else {
 return 0;
 }
}

并发编程的测试脚本:

for /L %n in (1,1,10) do java -cp ".;C:\Users\manyh\.m2\repository\ch\qos\logback\logbackclassic\1.2.3\logback-classic-1.2.3.jar;C:\Users\manyh\.m2\repository\ch\qos\logback\logbackcore\1.2.3\logback-core-1.2.3.jar;C:\Users\manyh\.m2\repository\org\slf4j\slf4japi\1.7.25\slf4j-api-1.7.25.jar" cn.itcast.n4.exercise.ExerciseSell

习题:转账问题

请改正:

public class ExerciseTransfer {
 public static void main(String[] args) throws InterruptedException {
     
 Account a = new Account(1000);
 Account b = new Account(1000);
 
 //a向b转账
 Thread t1 = new Thread(() -> {
 for (int i = 0; i < 1000; i++) {
 a.transfer(b, randomAmount());
 }
 }, "t1");
 //b向a转账
 Thread t2 = new Thread(() -> {
 for (int i = 0; i < 1000; i++) {
 b.transfer(a, randomAmount());
 }
 }, "t2");
     
     
 t1.start();
 t2.start();
 t1.join();
 t2.join();
     
  // 查看转账2000次后的总金额
 log.debug("total:{}",(a.getMoney() + b.getMoney()));
 }
 // Random 为线程安全
 static Random random = new Random();
 // 随机 1~100
 public static int randomAmount() {
 return random.nextInt(100) +1;
 }
}

class Account {
 private int money;
    
 public Account(int money) {
 this.money = money;
 }
    
 public int getMoney() {
 return money;
 }
    
 public void setMoney(int money) {
 this.money = money;
 }
    
 public void transfer(Account target, int amount) {
 if (this.money > amount) {
 this.setMoney(this.getMoney() - amount);
 target.setMoney(target.getMoney() + amount);
 }
 }
}

错误改正:

public synchronized void transfer(Account target, int amount) {
 if (this.money > amount) {
 this.setMoney(this.getMoney() - amount);
 target.setMoney(target.getMoney() + amount);
 }
}

正确改正:

public synchronized void transfer(Account target, int amount) {
     synchronized(Account.class) {
 if (this.money > amount) {
 this.setMoney(this.getMoney() - amount);
 target.setMoney(target.getMoney() + amount);
 }
     }        
}

因为这个例子是每个对象里都有一个共享变量,且互相有读写,如果只用对象加锁,仍然解决不了一个线程调用方法时,另一个线程仍能修改对方的问题,所以需要对类加锁。

4.6.Monitor概念

当我们使用sychronized关键字时,其实使用了底层的monitor对象,monitor是一种监控对象,他需要和一个java对象绑定,来监控临界区代码,同时分配所有权,得到所有权的线程可以使用临界区代码,无所有权的线程不能使用临界区代码。

QQ截图20220221155847

  • 当线程执行到临界区代码时,如果使用了synchronized,会先查询synchronized中所指定的对象(obj)是否绑定了Monitor

    • 如果没有绑定,则会先去去与Monitor绑定,并且将Owner设为当前线程。

    • 如果

      已经绑定

      ,则会去查询该Monitor是否已经有了Owner

      • 如果没有,则Owner与将当前线程绑定
      • 如果有,则放入EntryList,进入阻塞状态(blocked)
  • 当Monitor的Owner将临界区中代码执行完毕后,Owner便会被清空,此时EntryList中处于阻塞状态的线程会被叫醒并竞争,此时的竞争是非公平的

  • 注意

    • 对象在使用了synchronized后与Monitor绑定时,会将对象头中的Mark Word置为Monitor指针。
    • 每个对象都会绑定一个唯一的Monitor,如果synchronized中所指定的对象(obj)不同,则会绑定不同的Monitor

4.7.Synchronized原理进阶

4.7.1.对象头格式–重点聚焦 Mark Word

32位虚拟机:

QQ截图20220221171215

64位虚拟机:

QQ截图20220221171259

对于不同的锁状态,后两个位是不同的,系统会根据后两个位来判断当前对象的锁状态。

4.7.2.轻量级锁

轻量级锁使用场景:当一个对象被多个线程所访问,但访问的时间是错开的(不存在竞争),此时就可以使用轻量级锁来优化。

注意:自从jdk加入了锁优化,轻量级锁是使用sychronized关键字时就优先使用的。

使用过程

QQ截图20220221171635

QQ截图20220221172928

QQ截图20220221172933

null的情况代码如下:

static final Object obj = new Object();
public static void method1() {
 synchronized( obj ) {
 // 同步块 A
 method2();
 }
}
public static void method2() {
 synchronized( obj ) {
 // 同步块 B
 }
}

4.7.3.锁膨胀

QQ截图20220221171737

4.7.4.自旋优化

QQ截图20220221172054

自旋会占用 CPU 时间,单核 CPU 自旋就是浪费(比之前多了自旋的时间浪费时间片),多核 CPU 自旋才能发挥优势。

在 Java 6 之后自旋锁是自适应的,比如对象刚刚的一次自旋操作成功过,那么认为这次自旋成功的可能性会

高,就多自旋几次;反之,就少自旋甚至不自旋,总之,比较智能。

Java 7 之后不能控制是否开启自旋功能

4.7.5.偏向锁

轻量级锁在没有竞争时,每次重入(该线程执行的方法中再次锁住该对象)操作仍需要cas替换操作,这样是会使性能降低的。

所以引入了偏向锁对性能进行优化:在第一次cas时会将线程的ID写入对象的Mark Word中。此后发现这个线程ID就是自己的,就表示没有竞争,就不需要再次cas,以后只要不发生竞争,这个对象就归该线程所有。

减少了重复cas操作引起的效率问题。

偏向锁和轻量级锁对比

QQ截图20220222150737

偏向状态的判定

QQ截图20220222150858

偏向锁也是默认使用的,sychronized关键字的加锁后默认的启动顺序是:

偏向锁 -> 轻量级锁 -> 重量级锁 ->自旋优化

撤销偏向锁,取消偏向状态

以下几种情况会使对象的偏向锁失效

  • 调用对象的hashCode方法(放不下了)
  • 多个线程使用该对象
  • 调用了wait/notify方法(调用wait方法会导致锁膨胀而使用重量级锁
偏向锁的测试
  • 导入测试工具

QQ截图20220222085414

  • 测试一

QQ截图20220222085619

  • 测试二

QQ截图20220222152039

QQ截图20220222152101

偏向锁变为轻量级锁

QQ截图20220222152529

[t1] - 00000000 00000000 00000000 00000000 00011111 01000001 00010000 00000101 
[t2] - 00000000 00000000 00000000 00000000 00011111 01000001 00010000 00000101 //偏向给1线程
[t2] - 00000000 00000000 00000000 00000000 00011111 10110101 11110000 01000000 //2线程执行,变为轻量级锁
[t2] - 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001//无锁状态
批量重偏向

如果对象虽然被多个线程访问,但没有竞争,这时偏向了线程 T1 的对象仍有机会重新偏向 T2,重偏向会重置对象的 Thread ID

当撤销偏向锁阈值超过 20 次后,jvm 会这样觉得,我是不是偏向错了呢,于是会在给这些对象加锁时重新偏向至加锁线程

测试

QQ截图20220222153312

结果:

[t1] - 0 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 1 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 2 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 3 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 4 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 5 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 6 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 7 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 8 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 9 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 10 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 11 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 12 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 13 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 14 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 15 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 16 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 17 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 18 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 19 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 20 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 21 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 22 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 23 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 24 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 25 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 26 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 27 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 28 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t1] - 29 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t2] - ===============> 
[t2] - 0 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t2] - 0 00000000 00000000 00000000 00000000 00100000 01011000 11110111 00000000 
[t2] - 0 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001 

。。。。。    。。。。。
    
[t2] - 18 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 //原来锁状态
[t2] - 18 00000000 00000000 00000000 00000000 00100000 01011000 11110111 00000000 //轻量级锁
[t2] - 18 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001 //锁解除
//从20次开始,偏向锁指定变了,变成了t2
[t2] - 19 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 //t1的偏向锁
[t2] - 19 00000000 00000000 00000000 00000000 00011111 11110011 11110001 00000101 //从这变成了t2的偏向锁
[t2] - 19 00000000 00000000 00000000 00000000 00011111 11110011 11110001 00000101 
    
[t2] - 20 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t2] - 20 00000000 00000000 00000000 00000000 00011111 11110011 11110001 00000101 
[t2] - 20 00000000 00000000 00000000 00000000 00011111 11110011 11110001 00000101 
    
[t2] - 21 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t2] - 21 00000000 00000000 00000000 00000000 00011111 11110011 11110001 00000101 
[t2] - 21 00000000 00000000 00000000 00000000 00011111 11110011 11110001 00000101 
[t2] - 22 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t2] - 22 00000000 00000000 00000000 00000000 00011111 11110011 11110001 00000101 
[t2] - 22 00000000 00000000 00000000 00000000 00011111 11110011 11110001 00000101 
[t2] - 23 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t2] - 23 00000000 00000000 00000000 00000000 00011111 11110011 11110001 00000101 
[t2] - 23 00000000 00000000 00000000 00000000 00011111 11110011 11110001 00000101 
[t2] - 24 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t2] - 24 00000000 00000000 00000000 00000000 00011111 11110011 11110001 00000101 
[t2] - 24 00000000 00000000 00000000 00000000 00011111 11110011 11110001 00000101
[t2] - 25 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t2] - 25 00000000 00000000 00000000 00000000 00011111 11110011 11110001 00000101 
[t2] - 25 00000000 00000000 00000000 00000000 00011111 11110011 11110001 00000101 
[t2] - 26 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t2] - 26 00000000 00000000 00000000 00000000 00011111 11110011 11110001 00000101 
[t2] - 26 00000000 00000000 00000000 00000000 00011111 11110011 11110001 00000101 
[t2] - 27 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t2] - 27 00000000 00000000 00000000 00000000 00011111 11110011 11110001 00000101 
[t2] - 27 00000000 00000000 00000000 00000000 00011111 11110011 11110001 00000101 
[t2] - 28 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t2] - 28 00000000 00000000 00000000 00000000 00011111 11110011 11110001 00000101 
[t2] - 28 00000000 00000000 00000000 00000000 00011111 11110011 11110001 00000101 
[t2] - 29 00000000 00000000 00000000 00000000 00011111 11110011 11100000 00000101 
[t2] - 29 00000000 00000000 00000000 00000000 00011111 11110011 11110001 00000101 
[t2] - 29 00000000 00000000 00000000 00000000 00011111 11110011 11110001 00000101

要注意,偏向锁操作一般是对一个了类的所有对象起作用的,重偏向发生后,以后创建的对象也是重偏向。

下面要介绍的批量撤销也是这样。

批量撤销

当撤销偏向锁被更改超过 40 次后,再次被更改时,jvm 会这样觉得,自己确实偏向错了,根本就不该偏向。于是整个类的所有对象都会变为不可偏向的,新建的对象也是不可偏向的

测试

static Thread t1,t2,t3;
private static void test4() throws InterruptedException {
 Vector<Dog> list = new Vector<>();
 
    int loopNumber = 39;
//先让偏向锁偏向线程1
  t1 = new Thread(() -> {
 for (int i = 0; i < loopNumber; i++) {
 Dog d = new Dog();
 list.add(d);
 synchronized (d) {
 log.debug(i + "\t" + ClassLayout.parseInstance(d).toPrintableSimple(true));
 }
 }
 LockSupport.unpark(t2);
 }, "t1");
    

    t1.start();
//线程二改变偏向锁指向40次 
 t2 = new Thread(() -> {
 LockSupport.park();
 log.debug("===============> ");
 for (int i = 0; i < loopNumber; i++) {
 Dog d = list.get(i);
 log.debug(i + "\t" + ClassLayout.parseInstance(d).toPrintableSimple(true));
 synchronized (d) {
 log.debug(i + "\t" + ClassLayout.parseInstance(d).toPrintableSimple(true));
 }
 log.debug(i + "\t" + ClassLayout.parseInstance(d).toPrintableSimple(true));
 }
 LockSupport.unpark(t3);
 }, "t2");
 
    t2.start();
 //之后线程三再去改变偏向锁,此时就会变成轻量级锁,无论再改变几次
 t3 = new Thread(() -> {
 LockSupport.park();
 log.debug("===============> ");
 for (int i = 0; i < loopNumber; i++) {
 Dog d = list.get(i);
 log.debug(i + "\t" + ClassLayout.parseInstance(d).toPrintableSimple(true));
 synchronized (d) {
 log.debug(i + "\t" + ClassLayout.parseInstance(d).toPrintableSimple(true));
 }
 log.debug(i + "\t" + ClassLayout.parseInstance(d).toPrintableSimple(true));
 }
 }, "t3");
 
    t3.start();
 
    t3.join();
 
    log.debug(ClassLayout.parseInstance(new Dog()).toPrintableSimple(true));
}
锁消除

QQ截图20220222154947

QQ截图20220222154952

指定就是 当 Obeject对象o是一个不共享的局部变量,为了简洁,jvm会自动解除他在方法里以他为锁对象的锁。

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

java并发编程笔记(三)--管程(二) 的相关文章

  • 使用 ScriptEngine 从 JavaScript 调用 Java 方法

    我正在使用 ScriptEngine 运行 JavaScript 我希望 JavaScript 脚本能够调用 myFunction 其中 myFunction 是我的给定类中的一个方法 我知道可以将 importPackage 用于标准 J
  • Javadoc 链接到其他类中的方法

    目前我正在使用以下 Javadoc 语法引用其他类中的方法 see link com my package Class method 据我从文档中了解到 这是执行此操作的正确方法 但现在到了有趣的部分 或者说令人沮丧的部分 当我生成这个 j
  • 为什么用java日历解析时会得到错误的月份

    Date fakeDate sdf parse 15 07 2013 11 00 AM Calendar calendar Calendar getInstance calendar setTime fakeDate int current
  • Android 服务 START_STICKY START_NOT_STICKY

    我需要让我的服务始终在后台运行 并使用 startService 函数启动我的服务 无论应用程序的状态如何 我都不想重新启动服务 这是我的观察 START STICKY gt 如果应用程序启动 则服务正在重新启动 当应用程序关闭时 服务也会
  • 在 Java 中将字符串复制到文件的开头

    我想将一个字符串写入文件的开头 我该怎么做 我根本不知道如何添加字符串 这就是我到目前为止所做的 public static void prepend String filename String data throws IOExcepti
  • 获取文本文件中行的字节偏移量?

    我有一个文本文件 例如 one two three four five 我需要获取文件中每一行的偏移量 我如何在 Java 中做到这一点 我搜索了一些 I O 库 如 BufferedReader 和 RandomAccessFile 但我
  • rmi类找不到异常

    我使用 java rmi 编写了一个简单的项目并导出到可执行 jar 文件 当我尝试运行它时 有时会出现异常 有时会起作用 当我指定 Djava rmi server codebase file serverClasses 时 它似乎没有正
  • JAVA 签名对象 - 没有安装的提供程序支持此密钥:sun.security.rsa.RSAPrivateCrtKeyImpl

    我想使用密钥工具和以下命令创建的一对 RSA 密钥对我创建的文件进行签名 keytool genkeypair alias key keyalg RSA keysize 2048 sigalg SHA256withRSA validity
  • 在 XSSF 工作簿上设置密码保护

    我想为使用 poi 3 14 创建的 xlsx 文件添加密码保护 该文档声称 这是可能的 http poi apache org cryption html http poi apache org encryption html 使用我尝试
  • 错误:类 kotlin.reflect.jvm.internal.FunctionCaller$FieldSetter

    我已尝试一切方法来消除此错误 但它不断出现 Class kotlin reflect jvm internal FunctionCaller FieldSetter can not access a member of class com
  • 如何查找类路径中具有指定名称的所有资源?

    我想列出类路径中具有特定名称的所有文件 我预计会发生多次 因此Class getResource String 不管用 基本上 我必须识别类路径中任何位置具有特定名称 例如 xyz properties 的所有文件 然后累积读取其中的元数据
  • 如何使用 Java Streams API 将 Map 列表与列表值合并?

    我怎样才能减少Map
  • 何时对字符串文字使用 intern()

    我看到很多这样的遗留代码 class A public static final String CONSTANT value intern 我看不出使用 intern 的任何原因 因为在 Javadoc 中可以读到 所有文字字符串和字符串值
  • Thread.interrupt() 和 Thread.interrupted() 到底是如何工作的? [复制]

    这个问题在这里已经有答案了 从设置线程状态的角度来看 我不清楚这两种方法 Java 文档说 Thread interrupt 设置线程中断状态标志 调用 Thread interrupted 方法给出线程的状态并清除该标志 当这在实际场景中
  • 使用会话空闲超时进行轮询

    我对 Tomcat 中的所有应用程序使用单点登录 我的要求是 我必须轮询应从后端获取的事务状态 但它也不应该影响会话的空闲超时 有人可以建议是否可以做点什么吗 Thanx 我不知道是否有标准方法可以做到这一点 如果没有 你可以写一个过滤器
  • 在 x64 系统上使用 skype-java-api

    我正在使用 skype java api 在 Java 中使用 Skype 我需要的唯一功能是点击即可拨打电话号码 它在 Windows XP x86 上运行良好 但我刚刚在 Windows 7 x64 上测试它 但失败了 错误是 线程 T
  • Java:易失性足以使类线程安全?

    我有一个关于 Java 中 volatile 语句的问题 请看这个构造的例子 class Master Foo is a class with thread safe methods public volatile Foo foo clas
  • 项目级别的@PowerMockIgnore

    在 Maven 中运行时 我的 powermock 测试用例出现以下错误 java lang LinkageError loader constraint violation loader instance of org powermock
  • Cassandra 会话与集群 有什么可分享的?

    考虑 Cassandra 的 Session 和 Cluster 类 Java 驱动程序 我想知道有什么区别 在 Hibernate 中 每次都会创建一个会话并共享会话工厂 从许多来源我了解到 它被认为是创建一个会话并在多个线程之间共享它
  • Java编程编译jar

    我有一个文本文件中的java源代码 必须在源代码中输入一些自定义的硬编码变量 然后将其转换为 jar 这是可行的 但是当我运行 jar 时 找不到 Main 类 当我用 WinRAR 解压 jar 文件时 我似乎找不到错误 当我通过 cmd

随机推荐

  • vue-router "path" is required in a route configuration

    启用了动态路由 一直提示这个错误 页面打开也是空白 后来发现原来是component参数错误 正确的写法为 component gt import views own space own space vue 我错误的写为了 componen
  • 毕业设计 stm32 RFID智能仓库管理系统(源码+硬件+论文)

    文章目录 0 前言 1 主要功能 3 核心软件设计 4 实现效果 5 最后 0 前言 这两年开始毕业设计和毕业答辩的要求和难度不断提升 传统的毕设题目缺少创新和亮点 往往达不到毕业答辩的要求 这两年不断有学弟学妹告诉学长自己做的项目系统达不
  • 数据结构算法题——杂

    leetcode 7 整数反转 leetcode 7 整数反转 给你一个 32 位的有符号整数 x 返回将 x 中的数字部分反转后的结果 如果反转后整数超过 32 位的有符号整数的范围 231 231 1 就返回 0 假设环境不允许存储 6
  • 浅谈年轻人低存款状态与面临的困难

    目前 我的存款处于一万元以上的区间 对于我个人而言 存款并不是一件太过困难的事情 我秉持着理财的原则 通过合理的规划和节制开支 我能够将一部分收入用于存款 同时 我也会尽量避免不必要的消费 以确保有足够的资金用于应急和未来的规划 我相信 理
  • maven打包内存溢出,或者打包时间太长导致未知错误

    在idea中使用maven打包内存溢出问题 qq 27607447的博客 CSDN博客
  • numpy常用函数(一元通用函数、二元通用函数列表)

    Numpy通用函数 也可以称为ufunc 是一种在ndarray数据中进行逐个元素操作的函数 某些简单函数接受一个或多个标量数值 并产生一个或多个标量结果 而通用函数就是对这样简单函数的向量化封装 1 一元通用函数 比如sqrt或exp举例
  • 淘宝图片轮播代码

    下面图片轮播代码中 ul class lst main 与 ul 之间的代码为用户可以自定义修改的部分 为轮播的图片地址和超级连接地址信息 li a href http mb2 yubaibai com cn 201011 30 90221
  • String类常用方法系列八:替换

    1 String replace target value 替换指定字符 Test public void test1 String str 好好学习 天天向上 我爱学习 str str replace 好好学习 System out pr
  • 基于java-agent的监控

    jolokia是一个基于java agent的监控
  • UUID工具类

    import java util UUID public class Uuid public static String id32 String uuid UUID randomUUID toString uuid uuid replace
  • ehvierwer登录与不登录_《天涯明月刀手游》pc端手机端登录不进去如何解决 服务器已满快速解决方法...

    导读 天涯明月刀这款手游终于公测了 每个玩家都可以在这里创造属于自己的江湖世界 不同的人会有不同的旅程 所以想要拥有一段属于自己江湖旅程就一定不要错过天刀这款手游 不过这款游戏刚公测 有很多bug 不知道怎 天涯明月刀这款手游终于公测了 每
  • 机器语言->汇编语言->高级语言

    在硬件层面来看 计算机的运行就是高底电压的变化 这种高低电压的变化在早期是通过开关或插拔电线来控制的 计算机中用0和1来表示低电压和高电压 这些0和1的序列就可以控制计算机CPU进行各种动作 一组一组的0 1序列就是一个一个的指令 这些指令
  • springboot的日志管理

    springboot的默认日志管理 SprongBoot使用的默认日志框架是Logback 并用INFO级别输出到控制台 SpringBoot的日志的级别有7个 TRACE DEBUG INFO WARN ERROR FATAL OFF 日
  • SAP创建采购申请的时候供货源信息不完整

    如图所示 原先该物料的对应的供应商的采购信息记录已经维护好 货源清单也已经创建 但是在ME51N创建采购申请的时候发现红色框的供应商是没显示出来的 首先检查货源清单ME01 数据维护完整 然后返回到ME11采购信息记录中发现 有必填项没有维
  • 【华为OD机试】最少面试官数 (C++ Python Java)2023 B卷

    时间限制 C C 1秒 其他语言 2秒 空间限制 C C 262144K 其他语言524288K 64bit IO Format lld 题目描述 某公司组织一场公开招聘活动 假设由于人数和场地的限制 每人每次面试的时长不等 并已经安排给定
  • Layui框架的拖动上传 以及 时间选择器的基本使用

    上传用的layui的点击or拖动上传 其他上传也同理 不喜勿喷 欢迎补充 上代码 html div class layui form item style width 1 div
  • 使用代码下载开源的大模型文件示例以及中文微调llama资源汇总:

    一 下载示例 from huggingface hub import snapshot download repo id THUDM chatglm2 6b local dir chatglm2 6b cache dir local dir
  • 微信小程序 navigationStyle custom 无效

    因为项目风格要求 需要自定义导航栏 所以需要将默认的导航栏隐藏掉 隐藏的代码 倒很简单 只需要在相应的页面json文件中添加以下代码即可 navigationStyle custom 然后问题出来了 因为产品太多 需要将A产品的部分页面移植
  • 模拟电路设计(8)--- 耗尽型MOSFET

    上篇我们讲到增强型MOSFET的特点是 N沟道的建立是Ugs的贡献 没有Ugs gt Ut 导电沟道就无法建立 D S就不会有导通电流 这边我们要说的是另一种MOSFET 称为耗尽型MOSFET N沟道耗尽型MOSFET结构示意图 以N沟道
  • java并发编程笔记(三)--管程(二)

    习题 卖票 请改正 public class ExerciseSell public static void main String args 2000张票 TicketWindow ticketWindow new TicketWindo