【设计模式学习】单例模式和工厂模式

 ꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱
ʕ̯•͡˔•̯᷅ʔ大家好,我是xiaoxie.希望你看完之后,有不足之处请多多谅解,让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客
本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN 如需转载还请通知˶⍤⃝˶​
个人主页:xiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客

系列专栏:xiaoxie的JAVAEE学习系列专栏——CSDN博客●'ᴗ'σσணღ
我的目标:"团团等我💪( ◡̀_◡́ ҂)" 

( ⸝⸝⸝›ᴥ‹⸝⸝⸝ )欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​+关注(互三必回)! 

目录

 一.设计模式

1.什么是设计模式

2.设计模式的重要性

 二.单例模式

1.什么是单例模式

2.饿汉模式实现单例模式

1.Java代码

2.代码解释

3.是否为线程安全

3.懒汉模式实现单例模式

1.Java代码实现

2.代码解释

3.是否为线程安全

4.饿汉模式和懒汉模式的区别以及各自的优缺点和应用场景

1.饿汉模式和懒汉模式的区别

2.饿汉模式和懒汉模式的优缺点

3. 饿汉模式和懒汉模式的应用场景

三.工厂模式

1.什么是工厂模式

1.工厂模式的分类

2.工厂模式的应用场景

3.工厂模式的优点

4.工厂模式的缺点

5.总结

2.Java代码实现

1.简单工厂模式

2.工厂方法模式 

3.抽象工厂模式 


 

 一.设计模式

1.什么是设计模式

设计模式是在软件设计中反复出现的问题和解决方案的经验总结。它是对软件设计中常见问题的通用解决方案,可以帮助设计人员更高效地解决问题,并提高软件设计的质量和可维护性。设计模式提供了一种在特定情况下的解决方案,它们可以被反复使用,并且是经过验证的最佳实践。设计模式可以帮助开发人员更好地理解软件设计中的问题,并为他们提供一种标准的方法来解决这些问题。通俗易懂的一点来说:就是提高你的下限

设计模式就像是建筑行业的预制构件或者烹饪领域的配方,它为程序员在面对特定设计挑战时提供了一个经过验证、成熟且可复用的方案蓝图(都是大佬们写的绝对牛逼好用)。例如,在软件开发中,如果你需要创建多个相似对象,但又希望避免大量重复代码,你可以参考“工厂模式”来设计一个统一的创建接口;当你想要改变对象的行为,而又不修改对象本身时,可以运用“策略模式”动态地替换对象的算法。

所以,掌握和灵活运用设计模式,不仅能够提升编程效率,使得代码结构更加清晰合理,增强代码的可读性和可维护性,还能帮助团队成员之间通过共享的设计语言进行更有效的沟通与协作,从而提升整个项目的开发质量和效率。

2.设计模式的重要性

  1. 代码复用性

    • 设计模式为常见问题提供了标准化的解决方法,这些方法已经在实践中得到广泛验证,能够确保代码结构的稳定性。通过应用设计模式,开发人员可以创建模块化、可重用的组件,避免重复发明轮子,从而提高了代码的复用性。
  2. 代码可读性和可维护性

    • 使用设计模式能够使代码结构更加清晰,遵循一定的命名约定和组织原则,使得其他开发者更容易理解代码的工作机制,进而降低了维护成本。良好的设计模式应用还能减少由于代码复杂度引起的潜在错误。
  3. 系统灵活性与扩展性

    • 设计模式强调“开闭原则”,即对扩展开放,对修改关闭。这意味着设计模式鼓励构建低耦合、高内聚的系统,这样在不改动现有代码的基础上就能轻松添加新功能或适应变化的需求。
  4. 团队协作与沟通

    • 在团队开发环境中,设计模式充当了一种通用的设计语言,让开发人员能够快速准确地传达复杂的设计思想和实现策略,提高了团队成员间的沟通效率和协作水平。
  5. 软件质量提升

    • 应用设计模式通常意味着遵循最佳实践,这有助于提高软件的稳定性和健壮性,从而间接提升了软件产品的整体质量。
  6. 重构和优化

    • 设计模式提供了解决特定问题的标准途径,当需要对现有代码进行重构以改善性能或简化结构时,设计模式可作为指导方针,帮助开发人员安全高效地进行改造工作。

综上所述,设计模式不仅是提升个人编程技艺的有效工具,更是推动整个软件开发行业进步的关键要素之一。通过学习和掌握设计模式,开发人员能够构建出更加灵活、可维护、可靠且高效的软件系统。最重要的就是一句话,校招什么的常考,日常开发也用的很多

 二.单例模式

1.什么是单例模式

单例模式是一种常用的软件设计模式,它确保一个类只有一个实例(也就是在这个进程中,该类只能new出来一个对象),并提供一个全局访问点。这种模式在需要全局共享一个对象的场景中非常有用,例如:

  1. 资源管理

    • 数据库连接池:在整个应用程序运行期间,数据库连接通常是有限的宝贵资源,单例模式可以用来创建一个全局的数据库连接池,确保所有的数据库操作都共享这些连接,而不是频繁地创建和销毁连接。
    • 缓存服务:如Redis或Memcached客户端,通常作为单例实现,以便各个模块都可以共享同一份缓存连接,同时方便进行集中管理和配置。
  2. 日志服务

    • 日志系统通常会采用单例模式,确保整个应用程序只生成一个日志输出器实例,以统一格式和策略处理日志记录。
  3. 工具类

    • RestTemplateHttpClient等HTTP客户端工具类,在Spring框架中常常被设计成单例,避免每次请求都创建新的客户端实例,提高性能并便于集中配置。
    • 在前端开发中,某些全局配置或工具类也需要保证全局唯一,例如事件总线、通用函数库等。
  4. 配置管理

    • 应用程序配置读取类,可能需要在整个系统中共享一套配置,单例模式可以确保配置只加载一次并被全局复用。
  5. 多线程环境下的协调与控制

    • 单例模式可以用于充当线程间共享的协调者角色,比如线程池管理器、任务调度器等。
  6. 应用程序入口

    • 很多应用框架中的主入口类或者服务容器,为了保证整个应用生命周期内只有一个实例存在,会采用单例模式设计。
  7. 其他服务类

    • 文件系统访问类、消息队列客户端、图形用户界面组件工厂等场合,也可能用到单例模式来确保系统内只存在一个共享实例。

总之,任何需要在整个程序范围内保持唯一实例并且允许全局访问的对象,都是单例模式的适用场景 .

2.饿汉模式实现单例模式

1.Java代码

class Singleton {private static Singleton instance = new Singleton();public static Singleton getInstance() {return instance;}private Singleton() {}
}

2.代码解释

1private static Singleton instance = new Singleton(); 这里设为静态的,就意味着instance  为类属性,只有一个,并且和整个类的生命周期相同,在类被创建的同时被创建,被销毁时同时被销毁,初始化这个类自然也就只创建一次.并且因为只要这个类被创建,就实例化了一个对象,所以也被称为饿汉模式(饿了就先吃(提前实例化)”的特点).

2.public static Singleton getInstance() 获取单例对象的方法,它对外提供了一个全局访问点,任何时候调用此方法都将得到同一个Singleton实例. 

3. private Singleton() 可以看到该构造方法是被private所修饰的,也就意味着,其他类不能调用Singleton 类的构造方法,外部就不能通过new关键字实例化该类的对象,保证了单例的特性。当然如果你使用反射的话还是可以访问该方法的,

3.是否为线程安全

因为该类在被JVM创建后,由于instan是静态的也就是类属性,所以,会和该类同时被JVM创建,所以并不存在同步的问题,类加载的过程是由JVM保证线程安全的以在多线程环境下,即使多个线程同时首次访问Singleton getInstance() 方法,也只会有一个线程触发Singleton类的加载,因此它们都会得到相同的Singleton类的实例

3.懒汉模式实现单例模式

1.Java代码实现

class SingletonLazy {private static volatile SingletonLazy instance = null;public static SingletonLazy getInstance() {if(instance == null) {synchronized (SingletonLazy.class) {if(instance == null) {instance = new SingletonLazy();}}}return instance;}private SingletonLazy() {}
}

2.代码解释

1. private static volatile SingletonLazy instance = null;和饿汉模式不一样的是,一开始先不实例化对象,等到调用的getInstance()时候在实例化对象,这样就提高了效率,因为在实际开发中,实例化的对象中可能会包含很多数据,如果我们像饿汉模式一样一创建类就马上实例化对象,后续不一定一开始就需要使用这个对象,就浪费系统资源了,同时为了避免内存可见性问题,和指令重排序问题这里使用关键字 volatile 修饰该属性,避免出现线程安全问题.

2. public static SingletonLazy getInstance() 我们可以看到该方法块里的实例SingletonLazy 对象使用了双重检测以及加 synchronized 锁的方法,实例化对象,并且保证只实例化一次,以及避免线程安全问题,这里博主在通过画图来解释一下这里的双重检测以及加 synchronized 锁的方法,如何保证只实例化一次,以及避免线程安全问题.(因为懒汉模式是单例模式的最为常用的模式,这里需要重点掌握)

 总结来说就是:

  1. 第一次检查:在getInstance()方法的开始,首先检查instance是否已经被实例化。如果已经实例化,则直接返回该实例,这样可以避免不必要的同步操作,提高性能。

  2. 同步块:如果instance未被实例化,代码进入同步块。这里的同步操作是关键,它确保了在多线程环境下,只有一个线程能够执行同步块内的代码。

  3. 第二次检查:在同步块内部,进行第二次检查以确认instance是否仍然为null。这是必要的,因为可能在第一个线程检查instancenull并进入同步块的同时,其他线程也检查到instancenull。如果没有第二次检查,当第一个线程创建了实例并释放锁之后,其他线程可能会再次进入同步块并错误地创建新的实例。

  4. 实例化:如果第二次检查确认instance仍然为null,那么在同步块中创建单例对象,并将其实例赋值给instance

  5. 释放锁:完成实例化后,当前线程退出同步块,并释放锁,允许其他线程访getInstance()方法。

 3.private SingletonLazy()  和饿汉模式一样可以看到该构造方法是被private所修饰的,也就意味着,其他类不能调用Singleton 类的构造方法,外部就不能通过new关键字实例化该类的对象,保证了单例的特性。当然如果你使用反射的话还是可以访问该方法的.

3.是否为线程安全

由于懒汉模式为了延迟实例化对象,所以在创建类的时候没有一开始就实例化对象而是在调用getInstance()方法后再实例化对象,虽然节约了系统资源,但这样也就意味着在多线程的环境下,会发生线程安全问题,在上文博主解释了使用双重检测和synchronized上锁的机制保证了线程安全问题的一方面,为什么这里要说一方面呢,因为这里还有一个隐藏的线程安全问题即指令重排序问题,这个时候Instance就需要被关键字 volatile 所修饰,使得确保变量的读写操作对所有线程都是可见的,并且防止指令重排.这里博主再通用画图的形式讲解一下指令重排序问题

1.先解释一下什么是指令重排序

在编译器优化和处理器执行过程中,为了提高性能,可能会对指令序列进行重排序。这种重排序在单线程环境下通常不会引起问题,因为每个线程看到的指令执行顺序是一致的。但在多线程环境下,如果重排序导致内存操作的顺序发生变化,就可能出现数据不一致的问题。

使用小明去菜市场买菜来模拟一下cpu执行指令的过程.由于cpu执行指令是一条一条的执行的所以

可以发现这样买的效率就十分低效,所以呢大佬们就设计的编译器或者JVM就十分智能,可以根据实际情况生成指令的排序顺序,就会和原本写的代码的指令排序顺序有所差别,就像上图的例子,妈妈给了小明一个购物清单(代码),小明(编译器或者是JVM)就根据实际情况即( 鱼-> 猪肉 - > 卷心菜 - > 虾 -> 牛肉)对购物清单(代码)的顺序做出了修改,这样就大大提高了代码的执行效率,这种重排序在单线程环境下通常不会引起问题,因为每个线程看到的指令执行顺序是一致的。但在多线程环境下,如果重排序导致内存操作的顺序发生变化,就可能出现数据不一致的问题。

以上就是指令重排序的解释,现在再解释一下饿汉模式出现指令重排序问题的解释:

总结来说就是:

1.线程1获取到锁,判断 instance 为空的,就执行 instance = new SingletonLazy(); 这个操作,

2.这行代码被执行时,它实际上包含了三个步骤:

  1. 分配对象所需的内存空间。
  2. 调用构造函数初始化对象。
  3. instance引用指向分配的内存地址

3. 由于编译器或CPU可能对这三个步骤进行重排序:

      1.分配对象所需的内存空间。

      2.将instance引用指向分配的内存地址。

      3.调用构造函数初始化对象

4.先执行了将 instance引用指向分配的内存地址,但由于构造函数还未执行完毕,此时的 instance指向的是未初始化完成的对象.

5.此时线程2执行,读取到 instance为非空由于双重检测的缘故,就直接返回instance 

6.这里线程2返回的instance 对象并没有被初始化,这个时候就产生了BUG

7.所以我们就要一开始使用关键字 volatile 修饰 instance 能确保对instance的写操作(即实例化SingletonLazy对象)对所有线程立即可见,并且不会发生指令重排序,从而保证当其他线程读取到instance非空时,对应的SingletonLazy实例已经完全初始化完成.

8.上述说的场景虽然发生的概率很小,但是为了严谨性我们还是需要加入关键字 volatile 和 双重检测以及锁一起配合确保防止出现线程安全问题.

4.饿汉模式和懒汉模式的区别以及各自的优缺点和应用场景

1.饿汉模式和懒汉模式的区别

1.饿汉模式:饿汉模式在类加载时就完成了单例对象的初始化,也就是说,当类被载入到JVM时,单例就已经创建好了通常通过静态初始化块或直接在静态变量定义时初始化单例对象

2.懒汉模式是在第一次调用getInstance()方法时才进行实例化,即所谓的“懒加载”。需要处理线程安全问题,常见的做法有双重检查锁定。

2.饿汉模式和懒汉模式的优缺点

1.饿汉模式优点

  • 简单易懂,实现简单。
  • 线程安全,因为类加载过程由JVM保证是线程安全的。
  • 由于实例一开始就创建好了,所以在多线程环境下无须担心线程安全问题。

 2.饿汉模式缺点

  • 单例对象在程序启动时就创建,如果该对象比较大,或者初始化过程比较耗时,那么可能会造成内存资源的浪费,特别是如果这个单例对象在整个程序运行期间都不一定会被用到的情况下。

 3.懒汉模式优点

  延迟初始化,节约内存资源,尤其适合那些大型对象或者需要较多初始化操作的单例

  4.懒汉模式缺点

  • 普通懒汉模式实现不具备线程安全,需要额外的同步手段,如上述的双重检查锁定。
  • 双重检查锁定增加了代码复杂度,并且在某些Java版本(旧版)或特定条件下可能受指令重排序的影响,需要使用volatile关键字确保线程安全。

3. 饿汉模式和懒汉模式的应用场景

1.饿汉模式

  • 对象创建成本低,生命周期长,且预计会被频繁使用的场景。
  • 不依赖于其他外部资源初始化的场景。

2.懒汉模式

  • 对象创建成本高,生命周期短,或者不确定是否会被使用的场景。
  • 需要在真正需要时才初始化单例对象的场景。

 综上,选择饿汉模式还是懒汉模式取决于具体的使用场景,如果优先考虑内存优化和延迟初始化,可以选择懒汉模式;如果希望实现简单,对初始化时间不太敏感,或者确定单例对象必然会被使用,那么饿汉模式是一个更好的选择。

三.工厂模式

1.什么是工厂模式

工厂模式(Factory Pattern)是一种常用的创建型设计模式,它的目的是用来处理对象的创建机制。在软件开发中,对象的创建通常不是简单的实例化操作,还需要考虑诸如对象的重用、对象创建的封装、减少客户端与具体类的依赖等问题。工厂模式通过提供一个创建对象的接口,让子类决定实例化哪一个类,从而把对象的创建和使用进行分离。

1.工厂模式的分类

工厂模式主要分为以下三种类型:

  1. 简单工厂模式(Simple Factory)

    • 也称为静态工厂方法,通过一个单一的工厂类来创建不同类型的对象。
    • 工厂类通常包含多个静态方法,每个方法对应一种产品类的实例化。
    • 简单工厂模式的缺点是当产品类别增多时,工厂类的方法也会相应增多,导致难以维护。
  2. 工厂方法模式(Factory Method)

    • 定义了一个创建对象的接口,但让实现这个接口的类来决定实例化哪一个类。
    • 每个产品类都有一个对应的工厂类,负责创建该产品类的实例。
    • 工厂方法模式把产品的创建过程封装在具体的工厂类中,较好地解决了简单工厂模式的缺点。
  3. 抽象工厂模式(Abstract Factory)

    • 提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
    • 通常用于系统有多个产品族,且需要统一管理这些产品族的情况。
    • 抽象工厂模式允许客户端使用一个统一的接口来创建不同类型的产品,而不需要关心具体的实现。

2.工厂模式的应用场景

  • 当一个类不知道它所必须创建的具体类的时候。
  • 当一个类希望其子类来指定创建的对象时。
  • 当类的具体类应该由第三方来决定的时候。
  • 当系统不依赖于具体的类,而是依赖于它们共同的接口时。

3.工厂模式的优点

  • 解耦:将对象的创建和使用分离,客户端不需要知道具体的实现类,只需要知道它们的超类或接口。
  • 可扩展性:当需要添加新的产品类时,只需添加一个具体的类和对应的工厂类,而无需修改现有的代码。
  • 封装性:封装了产品的创建逻辑,客户端不需要关心产品的具体实现。
  • 代码清晰:使得客户端代码更加清晰,易于理解和维护。

4.工厂模式的缺点

  • 增加复杂性:对于简单工厂来说,可能会有大量的工厂类,增加了系统的复杂性。
  • 难以选择:对于客户端来说,可能需要从多个工厂类中选择一个合适的工厂来创建对象。

5.总结

工厂模式是一种非常实用的设计模式,它通过定义创建对象的接口,让子类决定具体要实例化的类,从而实现了对象创建和使用的分离。这种模式在实际开发中被广泛应用,特别是在需要灵活创建和管理对象的场景中。通过使用工厂模式,可以提高代码的可维护性、可扩展性和灵活性。

2.Java代码实现

1.简单工厂模式

// 简单工厂模式
interface Product {void show();
}class ConcreteProduct1 implements Product {@Overridepublic void show() {System.out.println("这是产品1");}
}class ConcreteProduct2 implements Product {@Overridepublic void show() {System.out.println("这是产品2");}
}class SimpleFactory {public static Product createProduct(String type) {if ("product1".equals(type)) {return new ConcreteProduct1();} else if ("product2".equals(type)) {return new ConcreteProduct2();} else {throw new IllegalArgumentException("无法识别的产品类型");}}
}// 使用
public class Main {public static void main(String[] args) {Product product1 = SimpleFactory.createProduct("product1");product1.show();Product product2 = SimpleFactory.createProduct("product2");product2.show();}
}

2.工厂方法模式 

// 工厂方法模式
interface Product {void show();
}class ConcreteProduct1 implements Product {@Overridepublic void show() {System.out.println("这是工厂1生产的具体产品1");}
}class ConcreteProduct2 implements Product {@Overridepublic void show() {System.out.println("这是工厂2生产的具体产品2");}// ... 更多具体产品类
}abstract class AbstractFactory {abstract Product createProduct();
}class ConcreteFactory1 extends AbstractFactory {@OverrideProduct createProduct() {return new ConcreteProduct1();}
}class ConcreteFactory2 extends AbstractFactory {@OverrideProduct createProduct() {return new ConcreteProduct2();}
}// 使用
public class Main {public static void main(String[] args) {AbstractFactory factory1 = new ConcreteFactory1();Product product1 = factory1.createProduct();product1.show();AbstractFactory factory2 = new ConcreteFactory2();Product product2 = factory2.createProduct();product2.show();}
}

3.抽象工厂模式 

// 抽象工厂模式
interface Color {void fill();
}interface Shape {void draw();
}class Red implements Color {@Overridepublic void fill() {System.out.println("填充红色");}
}class Blue implements Color {@Overridepublic void fill() {System.out.println("填充蓝色");}// ... 更多颜色类
}class Circle implements Shape {private Color color;public Circle(Color color) {this.color = color;}@Overridepublic void draw() {System.out.println("绘制圆形");color.fill();}
}class Square implements Shape {private Color color;public Square(Color color) {this.color = color;}@Overridepublic void draw() {System.out.println("绘制正方形");color.fill();}// ... 更多形状类
}interface AbstractFactory {Color getColor(String colorType);Shape getShape(String shapeType);
}class ShapeFactory implements AbstractFactory {@Overridepublic Color getColor(String colorType) {if ("Red".equalsIgnoreCase(colorType)) {return new Red();} else if ("Blue".equalsIgnoreCase(colorType)) {return new Blue();}return null;}@Overridepublic Shape getShape(String shapeType) {if ("Circle".equalsIgnoreCase(shapeType)) {return new Circle(getColor("Red")); // 这里假设默认使用红色} else if ("Square".equalsIgnoreCase(shapeType)) {return new Square(getColor("Blue")); // 这里假设默认使用蓝色}return null;}
}// 使用
public class Main {public static void main(String[] args) {AbstractFactory factory = new ShapeFactory();Shape circle = factory.getShape("Circle");circle.draw();Shape square = factory.getShape("Square");square.draw();}
}

以上就是关于设计模式的所有内容了,感谢你的阅读

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/815133.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【SpringBoot:详解Bean装配】

&#x1f3e1;Java码农探花&#xff1a; &#x1f525; 推荐专栏&#xff1a;<springboot学习> &#x1f6f8;学无止境&#xff0c;不骄不躁&#xff0c;知行合一 文章目录 前言一、IoC容器的简介BeanFactory接口源码二、Bean装配扫描装配探索启动类条件装配自定义Bean总…

版本管理|Git -目前最好的版本管理工具

文章目录 什么是版本为什么需要版本管理Git -目前最好的版本管理工具Git的关键特点和概念初始化Git保存代码改变git addgit commit -m ""git statusgit log branch分支管理git branch & git chekoutHEAD的本质git merge 合并fast forward merge 本地与远程如何解…

【一刷《剑指Offer》】面试题 3:二维数组中的查找

力扣对应题目链接&#xff1a;240. 搜索二维矩阵 II - 力扣&#xff08;LeetCode&#xff09; 核心考点&#xff1a;数组相关&#xff0c;特性观察&#xff0c;时间复杂度把握。 一、《剑指Offer》对应内容 二、分析题目 正常查找的过程本质就是排除的过程&#xff0c;谁排除…

【YOLOv9】完胜V8的SOTA模型Yolov9(论文阅读笔记)

官方论文地址&#xff1a; 论文地址点击即可跳转 官方代码地址&#xff1a; GitCode - 开发者的代码家园 官方代码地址点击即可跳转 1 总述 当输入数据经过各层的特征提取和变换的时候&#xff0c;都会丢失一定的信息。针对这一问题&#xff1a; 论文中提出的可编程梯度信息…

免费的 ChatGPT 网站(六个)

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《C》 《Linux》 《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 一、insCode二、讯飞星火三、豆包四、文心一言五、通义千问六、360智脑 现在智能…

【漏洞复现】WordPress LayerSlider插件SQL注入漏洞复现

声明&#xff1a;亲爱的读者&#xff0c;我们诚挚地提醒您&#xff0c;Aniya网络安全的技术文章仅供个人研究学习参考。任何因传播或利用本实验室提供的信息而造成的直接或间接后果及损失&#xff0c;均由使用者自行承担责任。Aniya网络安全及作者对此概不负责。如有侵权&#…

C数据结构:双向链表(带头循环)

前言 链表分多种&#xff0c;分别为 不带头不循环单向链表、不带头循环单向链表、带头循环单向链表、带头不循环单向链表 不带头不循环双向链表、不带头循环双向链表、带头循环双向链表、带头不循环双向链表 一共八种 在前一篇博客中完成的单链表即为不带头不循环单向链表…

杰发科技AC7840——CAN通信简介(5)_可变波特率设置

0. 简介 设置可变波特率时候&#xff0c;遇到2个坑&#xff0c;在此记录下来 使用该函数即可 can_time_segment_t bitrate2 s_canBitrate[CAN_BITRATE_250K]; CAN_DRV_SetBitrate(instance, &bitrate2); 1. 波特率指针注意不要空 查看设置波特率的接口&#xff0c;发现…

吉他弹唱谱怎么制作 Guitar Pro 怎么写弹简谱 Guitar Pro8.02简谱

学习如何制作吉他弹唱谱是提升音乐创作和表现能力的重要一环。借助专业的软件工具如Guitar Pro&#xff0c;可以轻松地将音乐创意转化为可视化的乐谱&#xff0c;使演奏和分享变得更加便捷和高效。下面我们来看看吉他弹唱谱怎么制作&#xff0c;Guitar Pro 怎么写弹简谱的相关内…

Llama 3下月正式发布,继续开源!

4月10日&#xff0c;Techcrunch消息&#xff0c;Meta在本周伦敦举办的一场活动中确定&#xff0c;下个月将正式发布Llama 3并且继续开源。 Meta全球事务总裁Nick Clegg表示&#xff0c;我们希望在下个月&#xff0c;甚至更短的时间内&#xff0c;正式推出新一代基础模型Llama …

机器学习和深度学习--李宏毅(笔记与个人理解)Day9

Day9 Logistic Regression&#xff08;内涵&#xff0c;熵和交叉熵的详解&#xff09; 中间打了一天的gta5&#xff0c;图书馆闭馆正好npy 不舒服那天天气不好&#xff0c;哈哈哈哈哈总之各种理由吧&#xff0c;导致昨天没弄起来&#xff0c;今天补更&#xff01; 这里重点注意…

面试官:实战中用过CountDownLatch吗?详细说一说,我:啊这...

写在开头 在很多的面经中都看到过提问 CountDownLatch 的问题&#xff0c;正好我们最近也在梳理学习AQS&#xff08;抽象队列同步器&#xff09;&#xff0c;而CountDownLatch又是其中典型的代表&#xff0c;我们今天就继续来学一下这个同步工具类&#xff01; CountDownLatc…

机器学习第34周周报VBAED

文章目录 week34 VBAED摘要Abstract一、文献阅读1. 题目2. abstract3. 网络架构3.1 序列问题阐述3.2 变分模态分解3.3 具有 BiLSTM 和双向输入注意力的编码器3.4 具有 BiLSTM 和双向时间注意力的解码器 4. 文献解读4.1 Introduction4.2 创新点4.3 实验过程4.3.1 数据集数据预处…

Redis为什么会变慢

链接: https://pan.baidu.com/s/1PNzhDMqkFBdKUu9_FxA5zw 提取码: euvk

以太网数据量大小字符串生成方法(可变单位)

0 前言 当我们想显示以太网数据量大小时&#xff0c;往往有个头疼的单位需要处理&#xff0c;单位取小了不一目了然&#xff0c;单位取大了精度太低。本例设计一个函数&#xff0c;将根据以太网数据量大小自动生成单位可变的字符串&#xff08;KB、MB、GB、TB、PB&#xff09;…

雷军 30 年前的病毒论文,结语最后一句是亮点

在 2023 雷军年度「成长」主题演讲中&#xff0c;他分享了自己在武汉大学设立的三个目标&#xff1a; 两年修完大学所有学分成为优秀的程序员在学报上发论文 对于彼时的在校生来说&#xff0c;在一级学报上发表论文是十分困难的事情&#xff0c;但雷军并没有因困难而畏惧、放…

【植物大战僵尸融合机器学习】+源码

上期回顾&#xff1a; 今天给大家推荐一个Gtihub开源项目&#xff1a;PythonPlantsVsZombies&#xff0c;翻译成中就是植物大战僵尸。 《植物大战僵尸》是一款极富策略性的小游戏。可怕的僵尸即将入侵&#xff0c;每种僵尸都有不同的特点&#xff0c;例如铁桶僵尸拥有极强的抗…

VRRP虚拟路由实验(华为)

思科设备参考&#xff1a;VRRP虚拟路由实验&#xff08;思科&#xff09; 一&#xff0c;技术简介 VRRP&#xff08;Virtual Router Redundancy Protocol&#xff09;是一种网络协议&#xff0c;用于实现路由器冗余&#xff0c;提高网络可靠性和容错能力。VRRP允许多台路由器…

APP开发_开发一个入门的 H5 APP

1 开发环境的搭建与准备 1.1 安装 Android Studio 下载&#xff1a;首先&#xff0c;从谷歌的安卓开发者网站&#xff08;https://developer.android.google.cn/studio/releases?hlzh-cn&#xff09;下载Android Studio的安装包。在下载页面中&#xff0c;可以根据自己的操作…

llamafactory:unified efficient fine-tuning of 100+ lanuage models

1.introduction llamafactory由三个主要模块组成&#xff0c;Model Loader&#xff0c;Data Worker&#xff0c;Trainer。 2.Efficient fine-tuning techniques 2.1 Efficient Optimization 冻结微调&#xff1a;冻结大部分参数&#xff0c;同时只在一小部分解码器层中微调剩…