JVM之垃圾回收

1. 如何判断对象可以回收

1.1 引用计数法

引用计数法是一种内存管理技术,其中每个对象都有一个与之关联的引用计数。引用计数表示当前有多少个指针引用了该对象。当引用计数变为零时,表示没有指针再指向该对象,该对象可以被释放,因为没有程序可以再访问它。

基本思想是在对象创建时初始化引用计数为1,每当有新的引用指向对象时,引用计数加1,当引用离开作用域或者被显式赋值为其他值时,引用计数减1。当引用计数为零时,释放对象的内存。

虽然引用计数法简单,但它有一些缺点,其中最主要的是不能解决循环引用的问题。如果两个或多个对象形成环状引用(彼此相互引用),它们的引用计数永远不会变为零,即使程序不再使用它们,这会导致内存泄漏。

1.2 可达性分析法

可达性分析是一种垃圾回收算法,用于确定在程序执行期间哪些对象是可访问的,即哪些对象可以被程序的根引用直接或间接访问到。这种算法通过从根引用出发,沿着对象之间的引用链,标记所有可达的对象,然后将未标记的对象认定为不可达,从而进行垃圾回收。

在可达性分析算法中,根对象是算法的起始点,从这些根对象开始追踪引用链以标记可达的对象。以下是一些典型的可达性分析算法的根对象:

  1. 虚拟机栈的本地变量引用的对象(Local Variables in Stack Frames):

    属于当前线程的栈帧中的本地变量可以作为根对象。这包括方法的参数、局部变量等。

  2. 本地方法栈中的变量引用的对象
    与虚拟机栈类似,但是用于支持本地方法(Native Method)的栈。

  3. 静态变量引用的对象(Static Variables):

    静态变量属于类而不是实例,因此在整个程序运行期间都存在。静态变量可以作为根对象,因为它们在程序的整个生命周期中都能被访问到。

  4. 常量引用的对象(Constant References):

    对于一些被认为是常量的引用,它们在整个程序运行期间都是可达的。这可能包括一些预定义的常量、静态 final 字段等。

  5. 活动的线程对象(Thread):

    线程对象本身可以被视为根对象。每个线程通常都有一个栈,栈中的内容(如本地变量)可以作为可达性分析的根。

  6. 被同步锁持有的对象(Locked Objects):

被Java线程持有的同步锁的对象,因为这些对象可能在其他线程中被访问。

  1. Java核心类库对象:

    如java.lang.Class对象。

这些根对象通常是垃圾回收器开始遍历引用链的起点。通过从这些根对象开始,垃圾回收器可以识别并标记所有通过引用链可达的对象,并最终确定哪些对象是不可达的,从而进行垃圾回收。

可达性分析算法的优点之一是它可以处理循环引用,因为只要一组对象是可达的,它们就不会被回收。这种算法通常与分代垃圾回收结合使用,以更有效地管理不同生命周期的对象。

Java虚拟机中的垃圾回收器(如G1收集器)就使用了可达性分析算法。这种算法的一个关键优势是,在进行垃圾回收的同时,程序的其他部分仍然可以继续执行,从而减小了垃圾回收对程序性能的影响。

1.3 四种引用

  1. 强引用

    强引用(Strong Reference)是Java中最普遍的引用类型。当一个对象具有强引用时,垃圾回收器不会回收这个对象,即使系统中存在内存不足的情况。只有当没有任何强引用指向一个对象时,该对象才会被垃圾回收器回收。

    在Java中,一般的对象引用,如赋值操作 Object obj = new Object(); 就是强引用。例如:

    Object obj = new Object();  // 强引用
    

    在这个例子中,obj 引用了一个新创建的 Object 对象。只要 obj 不被重新赋值为其他值,这个 Object 对象就会一直存在,不会被垃圾回收。

    强引用确保了对象的存在不会受到垃圾回收的影响,但也意味着程序员需要自己管理对象的生命周期,及时释放不再需要的引用,以便让垃圾回收器能够回收不再被引用的对象。

    Object obj = new Object();  // 强引用
    // 在某个时刻不再需要obj引用的对象
    obj = null;  // 将obj设置为null,释放对Object对象的强引用
    

    上述操作后,如果没有其他引用指向这个 Object 对象,它就变得不可达,最终可能被垃圾回收器回收。强引用的使用非常普遍,但需要谨慎管理,以避免内存泄漏或者持续占用过多内存的问题。

  2. 软引用

    软引用(Soft Reference)是Java中一种相对强引用更具弹性的引用类型。当一个对象只被软引用引用时,在内存不足时,这个对象可能被垃圾回收器回收,但它的回收是在系统判断内存不足的情况下进行的,因此相对于强引用来说,软引用更容易被回收。

    在Java中,可以使用java.lang.ref.SoftReference类来创建软引用。例如:

    import java.lang.ref.SoftReference;public class SoftReferenceExample {public static void main(String[] args) {// 创建一个字符串对象并使用软引用引用它String data = new String("Soft Reference Example");SoftReference<String> softReference = new SoftReference<>(data);// 现在,data可以被释放了,因为只有软引用引用它data = null;// 从软引用中获取对象String retrievedData = softReference.get();System.out.println(retrievedData);// 在这里模拟内存不足的情况simulateMemoryFull();// 再次尝试获取对象,如果内存不足,软引用可能被垃圾回收器回收retrievedData = softReference.get();System.out.println(retrievedData);}private static void simulateMemoryFull() {// 在这个方法中,模拟内存不足的情况,触发垃圾回收// 实际场景中,内存不足的情况可能由系统触发System.gc();}
    }

    在这个例子中,字符串对象被创建后,通过软引用 softReference 引用。然后,将 data 设置为 null,这意味着只有软引用引用这个字符串对象。在模拟内存不足的情况时,垃圾回收器可能会回收这个字符串对象。

    需要注意的是,软引用并不是一种确保对象被回收的机制,而是一种提供更灵活的回收策略的手段。软引用通常用于缓存等场景,允许在内存不足时释放一些缓存数据,而不会导致程序崩溃。

  3. 弱引用

    弱引用(Weak Reference)是Java中一种比软引用更弱的引用类型。与软引用类似,弱引用在垃圾回收时对对象的保护程度更低。当一个对象只被弱引用引用时,它在下一次垃圾回收时就有可能被回收,无论当前内存是否足够。

    在Java中,可以使用 java.lang.ref.WeakReference 类来创建弱引用。以下是一个简单的示例:

    import java.lang.ref.WeakReference;public class WeakReferenceExample {public static void main(String[] args) {// 创建一个字符串对象并使用弱引用引用它String data = new String("Weak Reference Example");WeakReference<String> weakReference = new WeakReference<>(data);// 现在,data可以被释放了,因为只有弱引用引用它data = null;// 从弱引用中获取对象String retrievedData = weakReference.get();System.out.println(retrievedData);// 在这里模拟内存不足的情况simulateMemoryFull();// 再次尝试获取对象,由于只有弱引用引用,对象可能被垃圾回收retrievedData = weakReference.get();System.out.println(retrievedData);}private static void simulateMemoryFull() {// 在这个方法中,模拟内存不足的情况,触发垃圾回收// 实际场景中,内存不足的情况可能由系统触发System.gc();}
    }

    在这个例子中,字符串对象被创建后,通过弱引用 weakReference 引用。然后,将 data 设置为 null,这意味着只有弱引用引用这个字符串对象。在模拟内存不足的情况时,垃圾回收器可能会回收这个字符串对象。

    弱引用通常用于一些临时性的缓存,当被引用对象不再被其他强引用引用时,垃圾回收器可以更自由地回收它们。弱引用的典型应用场景包括实现一些缓存策略,其中缓存项可以在内存紧张时被更容易地回收。

  4. 虚引用

    虚引用(Phantom Reference)是Java中最弱的一种引用类型,与弱引用和软引用不同,虚引用的存在几乎没有直接的影响。虚引用主要用于跟踪对象被垃圾回收的状态。

    在Java中,可以使用 java.lang.ref.PhantomReference 类来创建虚引用。虚引用并不能通过 get() 方法获取被引用的对象,而是通过配合引用队列(ReferenceQueue)来使用。当虚引用引用的对象被垃圾回收时,虚引用会被加入到引用队列中。

    以下是一个简单的虚引用示例:

    import java.lang.ref.PhantomReference;
    import java.lang.ref.ReferenceQueue;public class PhantomReferenceExample {public static void main(String[] args) {// 创建一个字符串对象并使用虚引用引用它String data = new String("Phantom Reference Example");ReferenceQueue<String> referenceQueue = new ReferenceQueue<>();PhantomReference<String> phantomReference = new PhantomReference<>(data, referenceQueue);// 现在,data可以被释放了,因为只有虚引用引用它data = null;// 在这里检查引用队列,看是否有虚引用进入// 虚引用入队后,表示对象即将被回收ReferenceQueue<String> queue = new ReferenceQueue<>();PhantomReference<String> phantomRef = new PhantomReference<>(data, queue);// 模拟垃圾回收的动作System.gc();// 检查引用队列,看是否有虚引用进入// 虚引用入队后,表示对象即将被回收java.lang.ref.Reference<? extends String> polledReference = referenceQueue.poll();if (polledReference != null) {System.out.println("PhantomReference is enqueued.");} else {System.out.println("PhantomReference is not enqueued.");}}
    }
    

    在这个例子中,字符串对象被创建后,通过虚引用 phantomReference 引用。然后,将 data 设置为 null,这意味着只有虚引用引用这个字符串对象。在模拟垃圾回收的动作时,我们检查引用队列,如果虚引用已经进入队列,表示相关对象即将被回收。

    虚引用通常用于一些特殊的清理操作,例如在对象被回收时执行一些资源释放或日志记录等。由于虚引用的特性,它并不能阻止被引用对象的回收。

  5. 终结器引用

    在Java中,终结器引用(Finalizer Reference)是一种与对象终结器(Finalizer)相关的引用。对象终结器是一个用于在对象被垃圾回收前执行清理操作的特殊方法,它由Object类中的finalize方法表示。

    终结器引用通常与对象的终结器方法相关联,通过 java.lang.ref.Finalizer 类进行管理。然而,需要注意的是,终结器机制在现代Java中被认为是不推荐使用的,因为它的执行时机不确定性,可能导致一系列问题,如内存泄漏和性能问题。

    以下是一个简单的示例,演示了终结器引用的使用:

    import java.lang.ref.Finalizer;class MyObject {@Overrideprotected void finalize() throws Throwable {System.out.println("Finalizing MyObject");}
    }public class FinalizerReferenceExample {public static void main(String[] args) {MyObject obj = new MyObject();// 创建终结器引用Finalizer<MyObject> finalizerReference = new Finalizer<>(obj, null);// 将对象置为null,使对象变为可终结obj = null;// 请求垃圾回收System.gc();// 在垃圾回收后,finalize方法可能被调用// 但不推荐依赖finalize方法执行清理操作}
    }

    在这个例子中,MyObject类重写了finalize方法,然后通过 Finalizer 类创建了一个终结器引用。当垃圾回收器请求垃圾回收时,finalize方法可能被调用。

    然而,强烈建议不要过度依赖终结器机制。替代终结器的方法包括使用try-with-resources结构、AutoCloseable接口以及其他清理模式。这些方法能够提供更可靠、可预测和有效的资源管理。

2. 垃圾回收算法

2.1 标记清除

标记清除算法(Mark and Sweep Algorithm)是一种基本的垃圾回收算法,用于找出不再被程序引用的对象并释放它们所占用的内存。该算法主要分为两个阶段:标记阶段和清除阶段。

以下是标记清除算法的基本步骤:

  1. 标记阶段(Marking Phase):

从根对象(GC Roots)开始,通过遍历对象引用链,标记所有被引用的对象。这个过程确保所有可达的对象都被标记为活动对象。

  1. 清除阶段(Sweeping Phase):

在清除阶段,垃圾回收器遍历整个堆,清除未被标记的对象。即,垃圾回收器释放那些没有在标记阶段被标记为活动对象的内存。清除的对象会被加入到可用的内存池,等待下次分配。

标记清除算法的优点在于它能够处理循环引用,因为它通过标记活动对象的方式,确保只有活动对象能够被保留。然而,这种算法也有一些缺点,例如:

  • 碎片化问题: 由于清除阶段释放的内存是不连续的,可能导致堆中出现碎片化,从而降低了内存的使用效率。

  • 效率问题: 清除阶段需要遍历整个堆,这在堆较大时可能会导致较长的停顿时间。

由于这些缺点,现代垃圾回收算法往往采用其他更高效的算法,如复制算法、标记-整理算法等。标记清除算法在教育和理论研究中仍然具有重要的地位,但在实际应用中,往往会选择更先进的垃圾回收算法。

2.2 标记整理

标记整理算法(Mark and Compact Algorithm)是一种垃圾回收算法,它结合了标记阶段、整理阶段和清除阶段,旨在减少内存碎片化。这个算法主要用于堆的管理,确保存活的对象在内存中是紧凑排列的,而非出现碎片。

以下是标记整理算法的基本步骤:

  1. 标记阶段(Marking Phase):

从根对象开始,通过遍历对象引用链,标记所有被引用的对象,将它们标记为活动对象。

  1. 整理阶段(Compacting Phase):

在整理阶段,垃圾回收器将所有活动对象向一端(通常是堆的起始端)移动,以便在移动过程中将空闲空间集中到堆的另一端。这一步骤类似于复制算法,但标记整理算法并不创建一个新的空间,而是在原有的堆中进行整理。

  1. 清除阶段(Sweeping Phase):

在清除阶段,垃圾回收器遍历整个堆,清除未被标记的对象。即,垃圾回收器释放那些没有在标记阶段被标记为活动对象的内存。

标记整理算法的优势在于它避免了标记清除算法的碎片化问题。通过整理阶段,存活的对象被移动到一起,而空闲的内存空间则被集中在一起,使得内存分配更为高效。但与此同时,标记整理算法仍然可能存在一定的停顿时间,因为整理阶段可能需要移动大量对象。

虽然标记整理算法在解决内存碎片问题上表现良好,但在某些场景下,如实时性要求较高的应用中,仍然可能会选择其他垃圾回收算法,如分代垃圾回收算法。

2.3 复制算法

复制算法(Copying Algorithm)是一种垃圾回收算法,主要用于解决内存碎片化的问题。该算法将堆分为两个区域:一个是活动对象存放的From空间,另一个是空闲空间的To空间。在每次垃圾回收时,将所有存活的对象从From空间复制到To空间,同时将From空间清空,然后交换From和To的角色,使得下一次垃圾回收时复制存活对象到新的To空间。

以下是复制算法的基本步骤:

  1. 标记阶段(Marking Phase):

从根对象开始,通过遍历对象引用链,标记所有被引用的对象,将它们标记为活动对象。

  1. 复制阶段(Copying Phase):

将所有活动对象从From空间复制到To空间。由于复制过程中保持了对象的相对顺序,因此无需移动引用。

  1. 更新引用(Update References):

更新所有指向被复制的对象的引用,使其指向新的To空间中的地址。

  1. 角色交换(Swap Roles):

交换From和To的角色,使To空间成为下一次垃圾回收的From空间。
复制算法的优点在于它解决了内存碎片的问题,因为新的To空间是一块干净的连续内存。然而,这种算法的缺点是它浪费了一半的内存空间,因为每次垃圾回收都需要有一块足够大的To空间来容纳所有活动对象。

复制算法通常用于新生代的垃圾回收,而在分代垃圾回收中,新生代采用复制算法,老年代则采用其他算法,如标记清除或标记整理算法。这样可以更好地平衡内存利用和垃圾回收效率。

3. 分代垃圾回收

分代垃圾回收是一种垃圾回收策略,根据对象的存活周期将堆内存划分为不同的代(Generation),并采用不同的垃圾回收算法和频率来处理每个代。这种策略基于两个观察:

  1. 弱存活假说(Weak Generational Hypothesis):

大部分对象在内存中存在的时间很短,而只有一小部分对象存活得较长。因此,可以将对象划分为新生代和老年代,分别采用不同的垃圾回收算法。

  1. 新生代的对象更容易死亡(Most objects die young):

大多数对象在被分配后很快就变得不可达,因此新生代中的对象更容易死亡。
分代垃圾回收一般将堆划分为三代:

  1. 新生代(Young Generation):

这是对象刚被分配的地方。新生代中的对象大多数是短命的。典型的垃圾回收算法是复制算法,因为复制算法适用于高回收率的场景。

  1. 老年代(Old Generation):

这是新生代中存活时间较长的对象被晋升到的地方。老年代中的对象更有可能长时间存活,因此采用标记清除或标记整理算法。

  1. 永久代(Permanent Generation):

用于存放静态不变的类信息、方法信息等。在JDK 8及以后的版本中,永久代被元空间(Metaspace)取代。
分代垃圾回收的优势在于它针对不同代采用不同的垃圾回收策略,根据对象的生命周期进行优化。这可以降低整体垃圾回收的成本,提高垃圾回收的效率。在实践中,分代垃圾回收策略被广泛应用于Java虚拟机和其他语言的运行时系统中。

4. 垃圾回收器

垃圾回收器是一种用于自动管理程序运行时内存的机制,它负责检测和回收不再被程序使用的内存对象,以便释放资源并防止内存泄漏。在Java和其他高级编程语言中,垃圾回收器是运行时系统的一部分。

以下是一些常见的垃圾回收器:

  1. 串行垃圾回收器(Serial Garbage Collector):

串行垃圾回收器是最基本的垃圾回收器,它使用单线程进行垃圾回收操作。适用于小型或简单的应用程序,但在大型应用中可能导致停顿时间较长。

  1. 并行垃圾回收器(Parallel Garbage Collector):

并行垃圾回收器使用多个线程进行垃圾回收操作,提高了垃圾回收的效率。适用于多核处理器的系统,可减少垃圾回收造成的停顿时间。

  1. 并发标记清除垃圾回收器(Concurrent Mark-Sweep Garbage Collector,CMS):

CMS垃圾回收器使用多线程进行标记和清除操作,以减少停顿时间。它适用于对停顿时间敏感的应用程序,但可能会牺牲一些吞吐量。

  1. G1垃圾回收器(Garbage First Garbage Collector):

G1垃圾回收器是一种面向大堆内存的垃圾回收器,旨在提供低停顿时间和高吞吐量。它将堆划分为多个区域,通过优先处理垃圾量较小的区域来降低停顿时间。

  1. Z垃圾回收器(Z Garbage Collector):

Z垃圾回收器是JEP 333引入的一种低停顿时间的垃圾回收器。它使用了一种称为Colored Pointers的技术,通过并发标记和整理的方式,减少了垃圾回收引起的停顿时间。

  1. Shenandoah垃圾回收器:

Shenandoah是一种低停顿时间的垃圾回收器,旨在减小大堆内存的垃圾回收停顿时间。它使用了一种被称为"Concurrent Compacting"的技术,通过并发标记和压缩来实现低停顿时间。
这些垃圾回收器具有不同的特性,选择哪个垃圾回收器取决于应用程序的性能需求、硬件配置以及对停顿时间的敏感性。在某些情况下,可以通过Java虚拟机的参数来选择或配置垃圾回收器。

5. 垃圾回收调优

JVM(Java Virtual Machine)的垃圾回收调优是优化Java应用程序性能和减少垃圾回收停顿时间的关键部分。以下是一些常见的JVM垃圾回收调优技巧:

  1. 选择合适的垃圾回收器:

    根据应用程序的性能需求和硬件配置,选择适合的垃圾回收器。例如,对于对停顿时间敏感的应用程序,可以考虑使用CMS(Concurrent Mark-Sweep)或G1(Garbage First)垃圾回收器。如果系统具有多核处理器,可以考虑使用并行垃圾回收器。

  2. 调整堆大小:

    根据应用程序的内存使用情况,调整堆的大小。合理的堆大小可以降低垃圾回收的频率,减小停顿时间。可以使用-Xms和-Xmx参数分别设置堆的初始大小和最大大小。

java -Xms256m -Xmx512m -jar YourApplication.jar
  1. 选择合适的垃圾回收策略:

    根据应用程序的内存使用模式,选择合适的垃圾回收策略。例如,对于短时间存活的对象较多的应用,考虑使用串行垃圾回收器或Parallel垃圾回收器。对于大堆内存,可以尝试使用G1垃圾回收器。

  2. 设置垃圾回收器相关的参数:

    针对选择的垃圾回收器,可以调整相关的参数。例如,对于CMS垃圾回收器,可以使用-XX:MaxGCPauseMillis参数设置最大停顿时间。

java -XX:+UseConcMarkSweepGC -XX:MaxGCPauseMillis=500 -jar YourApplication.jar
  1. 监控和分析垃圾回收日志:

    启用垃圾回收日志并进行监控分析是调优的重要手段。可以使用-XX:+PrintGCDetails和-Xloggc:gc.log参数来生成详细的垃圾回收日志。

    java -XX:+PrintGCDetails -Xloggc:gc.log -jar YourApplication.jar
    

    使用工具如jvisualvm、jConsole或专业的监控工具,对垃圾回收的情况进行实时监控和分析,以便及时发现潜在问题。

  2. 避免过度内存分配:

    减少不必要的对象创建和过度的内存分配有助于降低垃圾回收的压力。避免创建大量临时对象,尽可能使用对象池或重用对象的方式。

  3. 分析应用程序的内存使用情况:

    使用内存分析工具,如Eclipse Memory Analyzer(MAT)或VisualVM,深入了解应用程序的内存使用情况,找出可能的内存泄漏或不必要的内存占用。

这些调优技巧需要结合具体应用程序的特点进行调整,因为不同的应用有不同的内存使用模式和性能需求。定期进行性能测试和监控是调优的关键。

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

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

相关文章

HBase学习笔记(3)—— HBase整合Phoenix

目录 Phoenix Shell 操作 Phoenix JDBC 操作 Phoenix 二级索引 HBase整合Phoenix Phoenix 简介 Phoenix 是 HBase 的开源 SQL 皮肤。可以使用标准 JDBC API 代替 HBase 客户端 API来创建表&#xff0c;插入数据和查询 HBase 数据 使用Phoenix的优点 在 Client 和 HBase …

C++虚基类详解

多继承&#xff08;Multiple Inheritance&#xff09; 是指从多个直接基类中产生派生类的能力&#xff0c;多继承的派生类继承了所有父类的成员。尽管概念上非常简单&#xff0c;但是多个基类的相互交织可能会带来错综复杂的设计问题&#xff0c;命名冲突就是不可回避的一个。…

云原生Kubernetes系列 | 通过容器互联搭建wordpress博客系统

云原生Kubernetes系列 | 通过容器互联搭建wordpress博客系统 通过容器互联搭建一个wordpress博客系统。wordpress系统是需要连接到数据库上的,所以wordpress和mysql的镜像都是需要的。wordpress在创建过程中需要指定一些参数。创建mysql容器时需要把mysql的数据保存在宿主机本…

uni-app报错“本应用使用HBuilderX x.x.x 或对应的cli版本编译,而手机端SDK版本是x.x.x不匹配的版本可能造成应用异常”

uniapp开发的一个跨平台软件&#xff0c;在安卓模拟器上启动的时候报警告&#xff1a; 官方给的解释&#xff1a;uni-app运行环境版本和编译器版本不一致的问题 - DCloud问答 解决办法有两个 方法一&#xff1a;添加忽略警告的配置 项目根目录下找到 manifest.json&#xf…

C现代方法(第20章)笔记——底层程序设计

文章目录 第20章 底层程序设计20.1 位运算符20.1.1 移位运算符20.1.2 按位取反运算符、按位与运算符、按位异或运算符和按位或运算符20.1.3 用位运算符访问位20.1.4 用位运算符访问位域20.1.5 程序——XOR加密 20.2 结构中的位域20.2.1 位域是如何存储的 20.3 其他底层技术20.3…

计算机毕业设计 基于SpringBoot的销售项目流程化管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

k8s备份

cpu 磁盘io 往主的写&#xff0c;同步给备 rootk8s-etcd02:~# cat /etc/systemd/system/etcd.service [Unit] DescriptionEtcd Server Afternetwork.target Afternetwork-online.target Wantsnetwork-online.target Documentationhttps://github.com/coreos[Service] Typen…

high perfermance computer usage

简单记一下hpc的使用&#xff1a; hpc就是一些科研机构或者大学建立的服务器中心。我这大学的每一位学生&#xff0c;可以轻松使用hpc批量跑数据&#xff0c;也可以新建自己的server跑一些local data&#xff0c;后者每个学生账号最大是32核512G的运行内存&#xff0c;体验非常…

微信小程序 解决tab页切换过快 数据出错问题

具体问题&#xff1a;切换tab页切换过快时,上一个列表接口未响应完和当前列表数据冲突 出现数据错误 具体效果如下&#xff1a; 解决方式&#xff1a;原理 通过判断是否存在request 存在中断 并发送新请求 不存在新请求 let shouldAbort false; // 添加一个中断标志 let re…

量化交易:使用 python 进行股票交易回测

执行环境: Google Colab 1. 下载数据 import yfinance as yfticker ZM df yf.download(ticker) df2. 数据预处理 df df.loc[2020-01-01:].copy()使用了 .loc 方法来选择索引为 ‘2020-01-01’ 以后的所有行数据。通过 .copy() 方法创建了一个这些数据的副本&#xff0c;确…

星宿UI2.51资源付费变现小程序 支持流量主广告投放

目前&#xff0c;最新版的星宿UI是2.51版本。要搭建星宿UI&#xff0c;您需要准备备用域名、服务器和微信小程序账号。星宿UI提供了多项功能&#xff0c;包括文章展示、文章分类、资源链接下载和轮播图等。此外&#xff0c;还支持直接下载附件功能。这些功能使得星宿UI非常适合…

阶段七-Day01-SpringMVC

一、Sping MVC的介绍 1. 使用Front(前端)设计模式改写代码 1.1 目前我们的写法 目前我们所写的项目&#xff0c;持久层、业务层的类都放入到Spring容器之中了。他们之间需要注入非常方便&#xff0c;只需要通过Autowired注解即可。 但是由于Servlet整个生命周期都是被Tomca…

【开发工具】gitee还不用会?我直接拿捏 >_>

&#x1f308;键盘敲烂&#xff0c;年薪30万&#x1f308; 目录 git的一些前置操作 如何获取本地仓库 本地仓库的操作 远程仓库操作 合并两个仓库&#xff08;通用方法&#xff09; 从远程仓库拉取文件报错 fatal:refusing to merge unrelated histories 分支操作 注意&…

详解 KEIL C51 软件的使用·建立工程

单片机要运行,就必须将程序代码下载到程序存储器内部,但是在写进单片机之前要先将你写 的程序转换成*.hex 或*.bin 的文件.不同系列的单片机都有不同的软件对其进行编绎,而 keil Cx51 是德国开发的一个专为 51 系列单片机提供的软件开发平台,基本上现在的所有 51 系列内核的单片…

雷达波形及MATLAB仿真

文章目录 前言一、雷达波形二、Matlab 仿真1、SFW 的距离分辨率和距离模糊①、MATLAB 源码②、仿真结果 三、资源自取 前言 本文对雷达波形的内容以思维导图的形式呈现&#xff0c;有关仿真部分进行了讲解实现。 一、雷达波形 思维导图如下图所示&#xff0c;如有需求请到文章…

java源码用到的设计模式

Java 中有许多常用的设计模式&#xff0c;它们是为了解决特定问题而被反复使用和验证的经验总结。以下是一些常见的 Java 设计模式&#xff1a; 创建型模式 工厂模式 (Factory Pattern): 提供一个创建对象的接口&#xff0c;但是由子类决定实例化哪个类。例如&#xff1a;java…

产品的生命周期

** 没错&#xff0c;产品每次版本选代都是一次重生的机会&#xff0c;每次版本迭代都不亚于一次产品上线首发。 ** 一、产品上线首发 所谓万事开头难&#xff0c;产品上线首发的重要性不言而喻&#xff0c;产品给人的第一印象非常深刻&#xff0c;后期再去扭转非常困难&#…

GORM学习笔记

GORM学习笔记 官方文档&#xff1a;https://gorm.io/zh_CN/docs/ 1、数据准备 create table student (id int auto_incrementprimary key,sn varchar(20) null,name varchar(20) null,email varchar(20) null,class_id int null,monitor…

【第2章 Node.js基础】2.5 Node.js 的定时器

定时器timers 模块对外暴露一个全局的API用于调度在某个时段调用的函数因为定时器函数是全局变量&#xff0c;所以不需要加载timers 模块来使用它。Node.s 的定时器函敬实现了与 Web 浏览器提供的定时器 API 类似的 AP&#xff0c;但是它们使用了不同的内部实现机制&#xff0c…