并发编程原理与实战(四十)深入理解CopyOnWriteArrayList:核心API与线程安全设计

Java核心基础:从JVM原理到并发编程的实战知识体系构建 Java作为企业级应用开发的主流语言,其核心基础是构建稳定、高性能系统的基石。理解Java内存模型(JVM)的工作原理,包括堆、栈、方法区等运行时数据区的内存分配与垃圾回收机制,是诊断和解决内存溢出(OutOfMemoryError)等性能问题的关键。并发编程则是现代高并发系统的核心技术,涉及线程安全、锁机制(如synchronized和volatile)以及happens-before原则,用于保障多线程环境下的数据一致性与系统稳定性。这些基础知识的深度掌握,直接决定了开发者能否高效排查线上疑难杂症、进行 阅读详情

HashMap对应的线程安全类ConcurrentHashMap,本文来学习ArrayList对应的线程安全类CopyOnwriteArrayList。

认识CopyOnWriteArrayList

CopyOnWriteArrayList是java.util.concurrent中的一个线程安全的List实现。它使用“写时复制”(Copy-On-Write)的策略,即在修改操作(如添加、设置、删除元素)时,复制一份当前数组进行修改,而不是直接在原数组上修改。这样可以保证读操作无需加锁,且不会读取到正在修改的数组,从而实现了线程安全。

/**
 * A thread-safe variant of {@link java.util.ArrayList} in which all mutative
 * operations ({@code add}, {@code set}, and so on) are implemented by
 * making a fresh copy of the underlying array.
 *
 * <p>This is ordinarily too costly, but may be <em>more</em> efficient
 * than alternatives when traversal operations vastly outnumber
 * mutations, and is useful when you cannot or don't want to
 * synchronize traversals, yet need to preclude interference among
 * concurrent threads.  The "snapshot" style iterator method uses a
 * reference to the state of the array at the point that the iterator
 * was created. This array never changes during the lifetime of the
 * iterator, so interference is impossible and the iterator is
 * guaranteed not to throw {@code ConcurrentModificationException}.
 * The iterator will not reflect additions, removals, or changes to
 * the list since the iterator was created.  Element-changing
 * operations on iterators themselves ({@code remove}, {@code set}, and
 * {@code add}) are not supported. These methods throw
 * {@code UnsupportedOperationException}.
 *
 * <p>All elements are permitted, including {@code null}.
 *
 * <p>Memory consistency effects: As with other concurrent
 * collections, actions in a thread prior to placing an object into a
 * {@code CopyOnWriteArrayList}
 * <a href=" "><i>happen-before</i></a >
 * actions subsequent to the access or removal of that element from
 * the {@code CopyOnWriteArrayList} in another thread.
 *
 * <p>This class is a member of the
 * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
 * Java Collections Framework</a >.
 *
 * @since 1.5
 * @author Doug Lea
 * @param <E> the type of elements held in this list
 */
public class CopyOnWriteArrayList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    //......
}

CopyOnWriteArrayList是一种线程安全的java.util.ArrayList 变体,其中所有的修改操作(add、set等)都是通过创建底层数组的一个新副本来实现的。

通常这种做法代价较高,但当遍历操作远多于修改操作时,可能比其他替代方案更高效。当你无法或不想对遍历操作进行同步,但又需要防止并发线程之间的干扰时,这种实现非常有用。“快照”风格的迭代器方法使用在创建迭代器时数组状态的引用。在迭代器的生命周期内,这个数组永远不会改变,因此不可能发生干扰,且保证迭代器不会抛出 ConcurrentModificationException。迭代器不会反映自创建以来对列表进行的添加、删除或更改操作。不支持对迭代器本身进行更改元素的操作(remove、set和add)。这些方法会抛出UnsupportedOperationException。

允许所有元素,包括null。

内存一致性影响:与其他并发集合一样,在一个线程将对象存入CopyOnWriteArrayList之前的操作,先发生于(happen-before)另一个线程从CopyOnWriteArrayList 中访问或删除该元素之后的操作。

CopyOnWriteArrayList核心API

构造函数

在这里插入图片描述

(1)无参构造函数

......
    
/** The array, accessed only via getArray/setArray. */
private transient volatile Object[] array;

......
    
/**
 * Creates an empty list.
 */
public CopyOnWriteArrayList() {
    setArray(new Object[0]);
}
/**
 * Sets the array.
 */
final void setArray(Object[] a) {
    array = a;
}

创建一个空的 CopyOnWriteArrayList。从源码可以看出,setArray 方法用于设置底层存储数据的数组,这里初始化为一个长度为 0 的 Object 数组。

(2)参数为集合的构造函数

/**
 * Creates a list containing the elements of the specified
 * collection, in the order they are returned by the collection's
 * iterator.
 *
 * @param c the collection of initially held elements
 * @throws NullPointerException if the specified collection is null
 */
public CopyOnWriteArrayList(Collection<? extends E> c) {
    Object[] es;
    if (c.getClass() == CopyOnWriteArrayList.class)
        es = ((CopyOnWriteArrayList<?>)c).getArray();
    else {
        es = c.toArray();
        if (c.getClass() != java.util.ArrayList.class)
            es = Arrays.copyOf(es, es.length, Object[].class);
    }
    setArray(es);
}

使用给定集合中的元素初始化 CopyOnWriteArrayList。如果给定的集合本身就是 CopyOnWriteArrayList 类型,则直接复制其内部数组。否则,调用集合的 toArray 方法将其元素复制到一个新的数组中。
如果 toArray 返回的数组类型不是 Object[],则使用 Arrays.copyOf 方法将其复制到一个新的 Object[] 数组中。最后,调用 setArray 方法将新创建的数组设置为内部存储数组。

(3)参数为数组的构造函数

/**
 * Creates a list holding a copy of the given array.
 *
 * @param toCopyIn the array (a copy of this array is used as the
 *        internal array)
 * @throws NullPointerException if the specified array is null
 */
public CopyOnWriteArrayList(E[] toCopyIn) {
    setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class));
}

使用给定数组中的元素初始化 CopyOnWriteArrayList,通过复制数组来保证原始数组不会被修改。使用 Arrays.copyOf 方法将给定的数组复制到一个新的 Object[] 数组中。调用 setArray 方法将新创建的数组设置为内部存储数组。

添加元素

CopyOnWriteArrayList内部提供了多个添加元素的方法。
在这里插入图片描述

/**
 * Appends the specified element to the end of this list.
 *
 * @param e element to be appended to this list
 * @return {@code true} (as specified by {@link Collection#add})
 */
public boolean add(E e) {
    synchronized (lock) {
        Object[] es = getArray();
        int len = es.length;
        es = Arrays.copyOf(es, len + 1);
        es[len] = e;
        setArray(es);
        return true;
    }
}

从jdk21的源码中可以看出,add(E e)方法内部通过synchronized锁机制(jdk1.8的时候还是用ReentrantLock)来确保同一时间只有一个线程可以执行写操作:

  • 在添加元素之前,CopyOnWriteArrayList 会先获取当前的底层数组的快照,这个复制操作是通过 Arrays.copyOf 方法完成,生成一个新的数组,其长度比原数组大 1。遵循“写时复制”(Copy-On-Write)的策略。
  • 在新复制的数组上,将新元素添加到数组的末尾。
  • 将底层数组的引用指向新创建的数组,这样后续的读操作就会看到新添加的元素。

除了add(E e)方法,还提供了在数组特定位置添加元素add(int index, E element)、在数组头部添加元素addFirst(E e)、在数组尾部添加元素addLast(E e) 相关方法。

删除元素

CopyOnWriteArrayList内部同样提供了多个删除元素的方法。

/**
 * 删除指定索引处的元素,并返回被删除的元素。
 * 
 * @param index 要删除的元素的索引
 * @return 被删除的元素
 * @throws IndexOutOfBoundsException 如果索引超出范围(index < 0 || index >= size())
 */
public E remove(int index) {
    // 使用同步锁(lock)保证线程安全,同一时间只允许一个线程执行写操作
    synchronized (lock) { 
        // 获取当前底层数组的快照
        Object[] es = getArray(); 
        int len = es.length; // 当前数组长度
        
        // 获取要删除的元素(通过辅助方法 elementAt),供后续返回
        E oldValue = elementAt(es, index); 
        
        // 计算需要移动的元素数量:删除位置之后的元素个数
        int numMoved = len - index - 1; 
        
        Object[] newElements; // 定义新数组,用于存储删除后的元素
        
        // 如果删除的是最后一个元素,直接复制前 len-1 个元素到新数组
        if (numMoved == 0) { 
            newElements = Arrays.copyOf(es, len - 1); 
        } 
        // 否则,需要分两步复制:
        // 1. 复制删除位置之前的元素
        // 2. 复制删除位置之后的元素
        else { 
            newElements = new Object[len - 1]; // 创建新数组,长度减1
            // 复制删除位置之前的元素(从原数组的 0 到 index-1)
            System.arraycopy(es, 0, newElements, 0, index); 
            // 复制删除位置之后的元素(从原数组的 index+1 开始,复制到新数组的 index 位置)
            System.arraycopy(es, index + 1, newElements, index, numMoved); 
        }
        
        // 将底层数组的引用指向新数组,使后续操作基于新数组
        setArray(newElements); 
        
        // 返回被删除的元素
        return oldValue; 
    }
}

该方法是按索引删除‌元素,删除操作是写操作,同样需要加锁来确保同一时间只有一个线程能修改列表,避免数据竞争:

  • 在加锁后,CopyOnWriteArrayList 会先获取当前底层数组的快照。通用遵循“写时复制”(Copy-On-Write)的策略。
  • 复制操作通过 Arrays.copyOf方法完成,生成一个与原数组内容相同的新数组。
  • 在新数组上执行删除操作。
  • 将底层数组的引用指向新数组,使后续的读操作看到删除后的结果。

除了remove(int index)方法,还提供了删除数组头部元素removeFirst()、删除数组尾部元素removeLast()、按对象删除元素remove(Object o)、按索引范围删除元素removeRange(int fromIndex, int toIndex)等相关方法。

遍历元素

CopyOnWriteArrayList 的遍历操作基于“快照”机制,实现线程安全与弱一致性。遍历时直接访问底层数组的‌当前快照‌,无需加锁。遍历过程中,若其他线程修改列表(如添加/删除元素),迭代器‌不会感知变化‌,仍基于创建时的快照返回数据。遍历元素的方式主要有三种:

(1)通过迭代器遍历

/**
 * Returns an iterator over the elements in this list in proper sequence.
 *
 * <p>The returned iterator provides a snapshot of the state of the list
 * when the iterator was constructed. No synchronization is needed while
 * traversing the iterator. The iterator does <em>NOT</em> support the
 * {@code remove} method.
 *
 * @return an iterator over the elements in this list in proper sequence
 */
public Iterator<E> iterator() {
    return new COWIterator<E>(getArray(), 0);
}

迭代器创建时锁定当前数组快照,后续遍历不受写操作影响;迭代过程无需加锁且不支持删除元素操作。遍历过程中若列表被修改,迭代器‌不会抛出 ConcurrentModificationException‌。

示例代码:

CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.add("A");
list.add("B");
list.add("C");

// 获取迭代器(基于当前数组快照)
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String item = iterator.next();
     // 输出:A, B, C(顺序固定,不反映后续修改)
    System.out.println(item);
}

(2)通过 forEach 遍历

/**
 * @throws NullPointerException {@inheritDoc}
 */
public void forEach(Consumer<? super E> action) {
    Objects.requireNonNull(action);
    for (Object x : getArray()) {
        @SuppressWarnings("unchecked") E e = (E) x;
        action.accept(e);
    }
}

示例代码:

CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.add("A");
list.add("B");
list.add("C");

list.forEach(System.out::println);
list.forEach(item -> System.out.println(item));

(3)通过 get(int index) 遍历

/**
 * {@inheritDoc}
 *
 * @throws IndexOutOfBoundsException {@inheritDoc}
 */
public E get(int index) {
    return elementAt(getArray(), index);
}

示例代码:

CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.add("A");
list.add("B");
list.add("C");

for(String item : list){
    System.out.println(item);
}

for (int i = 0; i < list.size(); i++) {
	// 通过索引直接访问数组
    System.out.println(list.get(i)); 
}

与ArrayList 性能对比

以下是一个多线程并发读写测试代码,用于对比 CopyOnWriteArrayList 和 ArrayList 在并发环境下的性能和安全性差异。代码通过模拟多个线程同时读写列表,观察两者的表现。

public class CopyOnWriteArrayListTest {
    private static final int THREAD_COUNT = 20; // 线程数
    private static final int OPERATION_COUNT = 10000; // 每个线程的操作数
    private static final Random RANDOM = new Random();

    // 测试 CopyOnWriteArrayList
    private static class CopyOnWriteTest implements Runnable {
        private CopyOnWriteArrayList<Integer> list;
        private AtomicInteger successCount;

        public CopyOnWriteTest(CopyOnWriteArrayList<Integer> list, AtomicInteger successCount) {
            this.list = list;
            this.successCount = successCount;
        }

        @Override
        public void run() {
            for (int i = 0; i < OPERATION_COUNT; i++) {
                try {
                    if (RANDOM.nextBoolean()) {
                        list.add(RANDOM.nextInt(1000)); // 随机添加
                    }
                    successCount.incrementAndGet(); // 写成功计数
                } catch (Exception e) {
                    // 忽略失败(理论上 CopyOnWriteArrayList 不会失败)
                    System.out.println("CopyOnWriteArrayList写失败:" + e.getMessage());
                }
            }
        }

        public int getSuccessCount() {
            return successCount.get();
        }
    }

    // 测试普通 ArrayList(非线程安全)
    private static class ArrayListTest implements Runnable {
        private ArrayList<Integer> list;
        private AtomicInteger successCount;

        public ArrayListTest(ArrayList<Integer> list, AtomicInteger successCount) {
            this.list = list;
            this.successCount = successCount;
        }

        @Override
        public void run() {
            for (int i = 0; i < OPERATION_COUNT; i++) {
                try {
                    if (RANDOM.nextBoolean()) {
                        list.add(RANDOM.nextInt(1000));
                    }
                    successCount.incrementAndGet();
                } catch (Exception e) {
                    // 捕获并发修改异常(如 ConcurrentModificationException)
                    System.out.println("ArrayList写失败:" + e.getMessage());
                }
            }
        }

        public int getSuccessCount() {
            return successCount.get();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        // 测试 CopyOnWriteArrayList写
        CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>();
        testWrite(list, "CopyOnWriteArrayList");
        testRead(list, "CopyOnWriteArrayList");

        // 测试 ArrayList写
        ArrayList<Integer> list2 = new ArrayList<>();
        testWrite(list2, "ArrayList");
        testRead(list2, "ArrayList");
    }

    private static void testRead(List<Integer> list, String listType) throws InterruptedException {
        AtomicInteger successCount = new AtomicInteger(0);
        Thread[] threadArray1 = new Thread[THREAD_COUNT];
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < THREAD_COUNT; i++) {
            threadArray1[i] = new Thread(() -> {
                if (!list.isEmpty()) {
                    for (int j = 0; j < OPERATION_COUNT; j++) {
                        list.get(RANDOM.nextInt(list.size()));
                        successCount.incrementAndGet();
                    }
                }
            });
            threadArray1[i].start();
        }

        for (Thread t : threadArray1) {
            t.join();
        }
        long endTime = System.currentTimeMillis();
        System.out.println(listType + "测试完成,读成功操作数: " + successCount.get() + ",耗时:" + (endTime - startTime));
    }

    private static void testWrite(List<Integer> list, String listType) throws InterruptedException {
        AtomicInteger successCount = new AtomicInteger(0);
        Thread[] threadArray1 = new Thread[THREAD_COUNT];
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < THREAD_COUNT; i++) {
            if ("CopyOnWriteArrayList".equals(listType)) {
                CopyOnWriteTest copyOnWriteTask = new CopyOnWriteTest((CopyOnWriteArrayList<Integer>) list, successCount);
                threadArray1[i] = new Thread(copyOnWriteTask);
                threadArray1[i].start();
            }
            if ("ArrayList".equals(listType)) {
                ArrayListTest arrayListTask = new ArrayListTest((ArrayList<Integer>) list, successCount);
                threadArray1[i] = new Thread(arrayListTask);
                threadArray1[i].start();
            }
        }

        for (Thread t : threadArray1) {
            t.join();
        }
        long endTime = System.currentTimeMillis();
        System.out.println(listType + "测试完成,写成功操作数: " + successCount.get() + ",耗时:" + (endTime - startTime));
    }

}

运行结果:

CopyOnWriteArrayList测试完成,写成功操作数: 200000,耗时:3288
CopyOnWriteArrayList测试完成,读成功操作数: 200000,耗时:19
ArrayList写失败:Index 302 out of bounds for length 244
ArrayList测试完成,写成功操作数: 199999,耗时:28
ArrayList测试完成,读成功操作数: 200000,耗时:18

从运行结果可以看出,CopyOnWriteArrayList在读写性能上并不具备优势,而是在线程安全方面保证了数据的准确性。

Java并发编程:CountDownLatch核心原理、使用场景与实战解析 在Java多线程编程中,线程同步与协作是构建高并发、高性能应用的核心基础。其原理通常基于共享状态与等待/通知机制,通过协调多个线程的执行顺序来确保数据一致性与任务有序性。这一技术价值在于能够显著提升系统吞吐量、降低响应延迟,并优化资源利用率。常见的应用场景包括服务启动依赖检查、并行任务执行与结果汇总、批量数据处理等。本文聚焦于Java并发包中的CountDownLatch工具,深入解析其基于AQS(AbstractQueuedSynchronizer)的底层实现,并通过实战代码演示其在**多线程同步**与* 阅读详情

相关推荐

Java List.remove()方法深度解析:从原理到实战避坑指南

在Java集合框架中,List接口的remove()方法是操作列表数据的核心方法之一,它涉及数据结构基础与算法复杂度分析。其原理基于底层实现(如ArrayList的数组移位和LinkedList的节点指针修改),在删除元素时需考虑时间复杂度与内存操作效率。该技术的价值在于帮助开发者编写高性能、可维护的代码,避免常见的并发修改异常(ConcurrentModificationException)和性能陷阱。应用场景广泛,包括数据清洗、条件过滤、以及在处理如list parameter is not prese

weixin_33834628的博客 364

《Java并发编程:JUC核心解析与实战》

JUC (Java Util Concurrent) 是 Java 并发工具包,位于包下,提供了丰富的并发编程工具。它是在 Java 5 中引入的,旨在简化并发编程,提高代码质量和性能。JUC 的核心价值简化并发编程:提供高级并发工具,避免手动管理线程提高性能:充分利用多核CPU资源,实现高效的并发处理保证线程安全:内置线程安全机制,避免常见的并发问题提供丰富的并发工具:包括线程池、并发集合、原子类、锁机制等JUC 的设计理念无锁优先:优先使用无锁数据结构和算法细粒度锁:减少锁的粒度,提高并发性能异步编程。

King_model的博客 489

字节跳动Java后端面试核心考点与实战解析

Java后端开发在分布式系统和高并发场景下面临诸多挑战,理解JVM内存模型、并发编程原理及分布式架构设计是关键。JVM的GC调优涉及堆内存分析、GC策略选择等,而并发编程需掌握锁机制如synchronized与ReentrantLock的底层实现差异。分布式系统设计则聚焦高并发处理与数据一致性,例如短视频点赞计数器的Redis优化与MySQL索引失效问题。这些技术不仅提升系统性能,也广泛应用于电商、社交等业务场景。字节跳动面试尤其注重工程实践能力,通过白板编码和架构设计题考察候选人的实战思维与技术深度。

381

Java并发编程:同步机制原理与实战应用

在多线程编程中,同步机制是确保线程安全的核心技术。Java内存模型(JMM)定义了线程与内存的交互规则,解释了原子性、可见性和有序性三大并发问题。通过synchronized关键字、volatile变量和Lock接口等同步工具,开发者可以控制线程对共享资源的访问。这些机制在电商库存管理、高并发计数器等场景中发挥关键作用。文章深入分析Java内置同步机制的工作原理,比较synchronized与ReentrantLock的差异,并介绍ConcurrentHashMap等线程安全集合类的实现。掌握这些技术能有效

weixin_34129696的博客 423

AI时代Java面试转型:从八股文到深度设计与实战能力

在软件开发领域,技术面试一直是衡量程序员能力的重要环节。随着AI编程助手的普及,面试考察重点正从对基础概念的记忆转向对系统设计与实战能力的深度评估。这一转变的核心原理在于,AI能够高效生成标准代码和解释通用概念,但无法替代工程师在复杂业务场景下的架构权衡、高并发方案设计和线上问题定位能力。其技术价值在于更精准地筛选出具备解决真实工程问题能力的候选人,从而提升团队的技术交付质量。应用场景广泛覆盖Java基础、并发编程、JVM调优、MySQL优化、Spring框架及分布式系统设计等核心领域。例如,在并发编程中,

345

海康机器人ID5000 系列智能读码器(三)

又過了兩個月,漸漸的對這個攝像頭的功能更加熟悉了,而實際上,我要做的功能也越來越複雜,從一開始的讀碼,到後來的通過讀二維碼控制設備,再到未讀到二維碼控制設備等,下面就對具體的細項做一個總結。了解完這些就能對ID5000這個設備,乃至很多海康的設備都能做一個二次開發。

qq_54359036的博客 3070

Java集合框架核心原理与性能优化实战

Java集合框架是数据处理的基础工具,其核心原理基于数据结构与算法的高效实现。从数据结构角度看,ArrayList基于动态数组实现随机访问,LinkedList采用双向链表优化插入删除,HashMap则通过哈希表+红黑树解决冲突。在并发场景下,ConcurrentHashMap采用分段锁和CAS机制保证线程安全。实际开发中,合理选择集合类型和初始化参数能显著提升性能,如预估容量避免HashMap频繁扩容,根据访问模式选择ArrayList或LinkedList。集合框架在电商购物车、缓存系统等场景有广泛应用

weixin_33739646的博客 418

Zabbix监控联想服务器XCC的SNMPv3配置实战

本文详细介绍了如何通过SNMPv3协议配置Zabbix监控联想服务器XCC的实战方法。文章从安全角度阐述了选择SNMPv3的必要性,并分步讲解了在XCC中启用SNMPv3、创建认证用户,以及在Zabbix中导入专用模板、创建主机并关联模板的完整流程,帮助运维人员实现对服务器硬件健康状态的自动化、安全监控。

weixin_29210727的博客 464

集合框架核心知识点——线程安全JUC

JUC并发编程集合如CopyOnWriteArrayList和ConcurrentHashMap等常见方法原理,使用场景等

小萌新的博客 2777

激光光束质量评估与光斑尺寸计算:从理论到MATLAB实践

本文详细解析激光光束质量评估与光斑尺寸计算的理论基础及MATLAB实践方法,重点介绍M²因子的测量与应用。通过高斯光束模型、CCD成像法和MATLAB算法实现,帮助读者掌握从理论到实践的完整流程,提升激光系统调试与评估能力。

weixin_29083373的博客 444

使用 CFD 仿真进行阀门性能分析:第一部分

了解如何使用 Ansys Discovery 评估阀门性能,使工程师能够设计出更好的产品。

jkh920184196的博客 3144

Java面试核心:并发容器与内存优化实战

并发容器是Java多线程编程中的关键技术,通过CAS和锁分段等机制实现线程安全,有效解决高并发场景下的数据一致性问题。以ConcurrentHashMap为例,其底层采用Node数组+红黑树结构,配合CAS操作提升性能。内存优化则涉及JVM内存模型理解,包括堆区、方法区等核心区域的管理。常见问题如内存泄漏可通过MAT工具分析,而合理设置JVM参数能显著减少GC频率。这些技术在电商秒杀、金融交易等高并发系统中尤为重要,是Java开发者必须掌握的面试核心知识点。

weixin_34194359的博客 454

模型剪枝实战 | Torch-Pruning 库在YOLOv8上的应用指南

本文详细介绍了如何使用Torch-Pruning库对YOLOv8模型进行结构化剪枝,以实现模型“瘦身”。通过DepGraph(依赖图)技术自动处理层间依赖,确保剪枝安全。文章提供了从环境搭建、核心原理理解到完整剪枝流程的实战指南,并强调了剪枝后的微调与性能评估,帮助开发者在保持精度的同时显著提升模型推理速度。

weixin_29046035的博客 503

2025 Java面试核心指南:JVM、并发、框架原理与系统设计深度解析

Java作为企业级应用开发的主流语言,其技术生态围绕JVM(Java虚拟机)构建,理解JVM的内存模型、垃圾回收机制是掌握Java程序性能调优的基础。并发编程则是提升系统吞吐量的关键技术,涉及线程安全、锁机制及并发工具包(JUC)的应用。在分布式架构成为主流的今天,对Spring框架IoC/AOP原理、MySQL索引与事务、Redis缓存及消息队列等核心组件的深入理解,是构建高可用、高性能系统的基石。本文聚焦Java面试中的高频考点与实战场景,通过剖析JVM内存调优、HashMap扩容机制、秒杀系统设计等典

weixin_33770878的博客 533

stm32驱动NRF24L01_原理+代码解析

NRF24L01是NORDIC公司生产的一款无线通信通信芯片,采用FSK 调制,集成NORDIC自家的Enhanced Short Burst协议。可以实现点对点或是1对6的无线通信。无线通信速度最高可达到2Mbps。①2.4G全球开放的ISM频段,免许可证使用。②最高工作速率2Mbps,高校的GFSK调制,抗干扰能力强。③126个可选的频道,满足多点通信和调频通信的需要。④内置CRC检错和点对多点的通信地址控制。⑤可设置自动应答,确保数据可靠传输。//NRF24L01寄存器操作命令。

zyc18700766982的博客 2万+

QGIS安装与使用教程

QGIS安装与使用教程

weixin_46713695的博客 2万+

Java集合框架:高频面试考点与实战解析

Java集合框架是Java编程语言中用于存储和操作数据集合的核心组件,涵盖了数据结构、算法和并发编程等多个基础概念。从技术原理上看,集合框架通过接口分层设计(如Collection、Map等)实现了数据结构抽象,其底层采用动态数组、链表、红黑树等不同实现方式,直接影响着数据操作的性能表现。在工程实践中,合理选择ArrayList、HashMap等集合类能显著提升系统性能,特别是在高并发场景下,ConcurrentHashMap等并发集合的使用更是关键。集合框架不仅是Java面试的高频考点,更是实际项目开发中

weixin_33804582的博客 312

用 OP-TEE 给 AI 模型“上锁”:密文存储、TEE 解密放行、推理后销毁(实战可落地)

本文提出一种基于OP-TEE的AI模型保护方案,通过两级密钥体系确保模型静态存储为密文,运行时仅在TEE内解密。方案采用KEK+DEK架构,DEK永不出TEE,支持分块解密与可验证擦除。该方案能有效防御静态分析、应用层逆向等威胁,但需承认其物理级攻击的局限性。文章详细描述了端到端架构、文件格式设计及TA实现要点,包括密钥管理、分块解密策略和销毁机制,为设备侧AI部署提供了工程可行的安全解决方案。

Interview_TC的博客 288

Java后端面试攻略:从JVM调优、并发编程到AI集成与系统设计

Java虚拟机(JVM)是Java程序运行的基石,其内存模型与垃圾回收机制直接决定了应用的性能与稳定性。理解JVM内存区域划分、对象生命周期及不同垃圾收集器的工作原理,是进行性能调优和解决内存溢出等生产问题的关键。在并发编程领域,Java内存模型(JMM)通过volatile、synchronized及happens-before规则保障了多线程环境下的可见性、原子性与有序性,而AQS(AbstractQueuedSynchronizer)等底层框架则为构建高效并发工具提供了核心支持。这些核心技术为构建高可

weixin_33863087的博客 331

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Java并发编程最全面试题(三万字推荐)

java并发编程面试题,线程,线程池,同步

九离的博客 719

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Java集合框架深度解析:从数据结构到并发容器实战

集合框架是Java语言中用于存储和操作数据组的核心API,其设计基于经典的数据结构理论,如数组、链表、哈希表和树。理解其底层原理,例如HashMap的哈希冲突解决与扩容机制,是掌握Java基础的关键。这些技术价值在于,它们直接决定了程序在数据存取、遍历和修改时的性能表现,是构建高效、稳定应用的基础。在实际开发中,集合被广泛应用于缓存管理、任务调度、数据聚合等场景。本文聚焦于Java集合框架的深度解析,特别是针对高并发环境下的线程安全容器,如ConcurrentHashMap的锁分段与CAS优化,以及Copy

weixin_30435261的博客 400

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Java核心知识体系构建:从基础语法到JVM实战的完整指南

面向对象编程(OOP)是软件开发的基石,其封装、继承、多态三大特性为构建模块化、可复用的代码提供了理论框架。在Java语言中,这一原理通过类、接口、抽象类等机制得以实现,其技术价值在于提升代码的可维护性和扩展性。在实际应用场景中,开发者需要深入理解集合框架(如HashMap的树化机制)、并发编程(如volatile关键字与内存模型)以及JVM内存管理(如GC算法与调优)等核心组件,才能设计出高性能、高可用的系统。本文聚焦Java知识体系的有机串联,针对ArrayList与LinkedList的选型、Conc

weixin_30443731的博客 409

Java面试系统备战指南:从核心原理到实战场景突破

Java作为企业级应用开发的核心技术栈,其底层原理和工程实践是开发者必须掌握的基础。理解JVM内存模型、垃圾回收机制等核心概念,能够帮助开发者编写高性能、高可用的应用程序。在并发编程领域,线程安全、锁机制等原理知识为构建稳定分布式系统提供技术保障。这些技术价值体现在系统性能优化、资源利用率提升等实际场景中。随着面试要求的不断提高,候选人需要系统掌握Java基础、Spring全家桶、MySQL优化等热点技术。本文基于大模型辅助学习和场景题拆解等热词方法,提供从原理到实战的完整备战方案,帮助开发者在竞争激烈的J

weixin_30376083的博客 383

AI时代Java程序员如何构建核心竞争力:从原理到实战的转型指南

在软件开发领域,自动化工具和人工智能辅助编程正逐渐改变开发范式。其核心原理在于通过模式识别和代码生成,提升基础编码环节的效率。这一技术进步带来的核心价值是解放开发者,使其能更专注于复杂系统设计、性能优化和架构决策等高阶任务。对于Java开发者而言,这意味着应用场景从传统的CRUD实现,转向对JVM原理、高并发处理、数据库深度优化及分布式系统等底层技术的驾驭。掌握这些硬核知识,结合AI工具进行高效学习和问题排查,成为构建不可替代技术护城河的关键。本文聚焦于如何利用AI应对面试与深化Java核心技术栈,帮助开发

chupu2979的博客 376

万字整理JavaSE核心知识:从面向对象到并发编程的实战指南

面向对象编程是Java语言的基石,其核心思想包括封装、继承和多态,旨在通过抽象和模块化提升代码的可维护性与复用性。在Java标准版中,集合框架、IO流和多线程并发是支撑工程实践的关键技术组件。集合框架如HashMap通过数组、链表和红黑树的数据结构实现高效的数据存储与检索,其扩容机制和线程安全问题是开发中的常见考点。多线程并发编程则涉及线程生命周期管理、同步机制以及JMM内存模型,其中synchronized关键字和volatile变量分别用于保证原子性与可见性,是构建高并发应用的基础。这些技术共同服务于企

aodiyi6351的博客 394
上一篇: 开发避坑指南(73):itext7 pdf表单字体加粗解决方案
帧栈
博客等级 码龄2年 335粉丝 120原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

帧栈

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值