如何在阿里巴巴上建设公司网站/东莞谷歌推广公司

如何在阿里巴巴上建设公司网站,东莞谷歌推广公司,028网站建设工作室,wordpress页面设置教程大纲 1.并发安全的数组列表CopyOnWriteArrayList 2.并发安全的链表队列ConcurrentLinkedQueue 3.并发编程中的阻塞队列概述 4.JUC的各种阻塞队列介绍 5.LinkedBlockingQueue的具体实现原理 6.基于两个队列实现的集群同步机制 1.并发安全的数组列表CopyOnWriteArrayList …

大纲

1.并发安全的数组列表CopyOnWriteArrayList

2.并发安全的链表队列ConcurrentLinkedQueue

3.并发编程中的阻塞队列概述

4.JUC的各种阻塞队列介绍

5.LinkedBlockingQueue的具体实现原理

6.基于两个队列实现的集群同步机制

1.并发安全的数组列表CopyOnWriteArrayList

(1)CopyOnWriteArrayList的初始化

(2)基于锁 + 写时复制机制实现的增删改操作

(3)使用写时复制的原因是读操作不加锁 + 不使用Unsafe读取数组元素

(4)对数组进行迭代时采用了副本快照机制

(5)核心思想是通过弱一致性提升读并发

(6)写时复制的总结

(1)CopyOnWriteArrayList的初始化

并发安全的HashMap是ConcurrentHashMap

并发安全的ArrayList是CopyOnWriteArrayList

并发安全的LinkedList是ConcurrentLinkedQueue

从CopyOnWriteArrayList的构造方法可知,CopyOnWriteArrayList基于Object对象数组实现。

这个Object对象数组array会使用volatile修饰,保证了多线程下的可见性。只要有一个线程修改了数组array,其他线程可以马上读取到最新值。

//A thread-safe variant of java.util.ArrayList in which all mutative operations 
//(add, set, and so on) are implemented by making a fresh copy of the underlying array.
public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { ...//The lock protecting all mutatorsfinal transient ReentrantLock lock = new ReentrantLock();//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;}...
}

(2)基于锁 + 写时复制机制实现的增删改操作

一.使用独占锁解决对数组的写写并发问题

每个CopyOnWriteArrayList都有一个Object数组 + 一个ReentrantLock锁。在对Object数组进行增删改时,都要先获取锁,保证只有一个线程增删改。从而确保多线程增删改CopyOnWriteArrayList的Object数组是并发安全的。注意:获取锁的动作需要在执行getArray()方法前执行。

但因为获取独占锁,所以导致CopyOnWriteArrayList的写并发并性能不太好。而ConcurrentHashMap由于通过CAS设置 + 分段加锁,所以写并发性能很高。

二.使用写时复制机制解决对数组的读写并发问题

CopyOnWrite就是写时复制。写数据时不直接在当前数组里写,而是先把当前数组的数据复制到新数组里。然后再在新数组里写数据,写完数据后再将新数组赋值给array变量。这样原数组由于没有了array变量的引用,很快就会被JVM回收掉。

其中会使用System.arraycopy()方法和Arrays.copyOf()方法来复制数据到新数组,从Arrays.copyOf(elements, len + 1)可知,新数组的大小比原数组大小多1。

所以CopyOnWriteArrayList不需要进行数组扩容,这与ArrayList不一样。ArrayList会先初始化一个固定大小的数组,然后数组大小达到阈值时会扩容。

三.总结

为了解决CopyOnWriteArrayList的数组写写并发问题,使用了锁。

为了解决CopyOnWriteArrayList的数组读写并发问题,使用了写时复制。

所以CopyOnWriteArrayList可以保证多线程对数组写写 + 读写的并发安全。

//A thread-safe variant of java.util.ArrayList in which all mutative operations 
//(add, set, and so on) are implemented by making a fresh copy of the underlying array.
public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { ...//The lock protecting all mutatorsfinal transient ReentrantLock lock = new ReentrantLock();//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;}//Gets the array. Non-private so as to also be accessible from CopyOnWriteArraySet class.final Object[] getArray() {return array;}//增:Appends the specified element to the end of this list.public boolean add(E e) {final ReentrantLock lock = this.lock;lock.lock();try {Object[] elements = getArray();int len = elements.length;Object[] newElements = Arrays.copyOf(elements, len + 1);newElements[len] = e;setArray(newElements);return true;} finally {lock.unlock();}}//删:Removes the element at the specified position in this list.//Shifts any subsequent elements to the left (subtracts one from their indices).  //Returns the element that was removed from the list.public E remove(int index) {final ReentrantLock lock = this.lock;lock.lock();try {Object[] elements = getArray();int len = elements.length;E oldValue = get(elements, index);int numMoved = len - index - 1;if (numMoved == 0) {setArray(Arrays.copyOf(elements, len - 1));} else {//先创建新数组,新数组的大小为len-1,比原数组的大小少1Object[] newElements = new Object[len - 1];//把原数组里从0开始拷贝index个元素到新数组里,并且从新数组的0位置开始放置System.arraycopy(elements, 0, newElements, 0, index);//把原数组从index+1开始拷贝numMoved个元素到新数组里,并且从新数组的index位置开始放置;System.arraycopy(elements, index + 1, newElements, index, numMoved);setArray(newElements);}return oldValue;} finally {lock.unlock();}}//改:Replaces the element at the specified position in this list with the specified element.public E set(int index, E element) {final ReentrantLock lock = this.lock;lock.lock();try {Object[] elements = getArray();E oldValue = get(elements, index);if (oldValue != element) {int len = elements.length;Object[] newElements = Arrays.copyOf(elements, len);newElements[index] = element;setArray(newElements);} else {//Not quite a no-op; ensures volatile write semanticssetArray(elements);}return oldValue;} finally {lock.unlock();}}...
}

(3)使用写时复制的原因是读操作不加锁 + 不使用Unsafe读取数组元素

CopyOnWriteArrayList的增删改采用写时复制的原因在于get操作不需加锁。get操作就是先获取array数组,然后再通过index定位返回对应位置的元素。

由于在写数据的时候,首先更新的是复制了原数组数据的新数组。所以同一时间大量的线程读取数组数据时,都会读到原数组的数据,因此读写之间不会出现并发冲突的问题。

而且在写数据的时候,在更新完新数组之后,才会更新volatile修饰的数组变量。所以读操作只需要直接对volatile修饰的数组变量进行读取,就能获取最新的数组值。

如果不使用写时复制机制,那么即便有写线程先更新了array引用的数组中的元素,后续的读线程也只是具有对使用volatile修饰的array引用的可见性,而不会具有对array引用的数组中的元素的可见性。所以此时只要array引用没有发生改变,读线程还是会读到旧的元素,除非使用Unsafe.getObjectVolatile()方法来获取array引用的数组的元素。

public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {...//The array, accessed only via getArray/setArray.private transient volatile Object[] array;//Gets the array.  Non-private so as to also be accessible from CopyOnWriteArraySet class.final Object[] getArray() {return array;}public E get(int index) {//先通过getArray()方法获取array数组,然后再通过get()方法定位到数组某位置的元素return get(getArray(), index);}private E get(Object[] a, int index) {return (E) a[index];}...
}

(4)对数组进行迭代时采用了副本快照机制

CopyOnWriteArrayList的Iterator迭代器里有一个快照数组snapshot,该数组指向的就是创建迭代器时CopyOnWriteArrayList的当前数组array。

所以使用CopyOnWriteArrayList的迭代器进行迭代时,会遍历快照数组。此时如果有其他线程更新了数组array,也不会影响迭代的过程。

public class CopyOnWriteArrayListDemo {static List<String> list = new CopyOnWriteArrayList<String>();public static void main(String[] args) {list.add("k");System.out.println(list);Iterator<String> iterator = list.iterator();while (iterator.hasNext()) {System.out.println(iterator.next());}}
}public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {...public Iterator<E> iterator() {return new COWIterator<E>(getArray(), 0);}...static final class COWIterator<E> implements ListIterator<E> {private final Object[] snapshot;private int cursor;private COWIterator(Object[] elements, int initialCursor) {cursor = initialCursor;snapshot = elements;}...}...
}

(5)核心思想是通过最终一致性提升读并发

CopyOnWriteArrayList的核心思想是通过弱一致性来提升读写并发的能力。

CopyOnWriteArrayList基于写时复制机制存在的最大问题是最终一致性。

多个线程并发读写数组,写线程已将新数组修改好,但还没设置给array。此时其他读线程读到的(get或者迭代)都是数组array的数据,于是在同一时刻,读线程和写线程看到的数据是不一致的。这就是写时复制机制存在的问题:最终一致性或弱一致性。

(6)写时复制的总结

一.优点

读读不互斥,读写不互斥,写写互斥。同一时间只有一个线程可以写,写的同时允许其他线程来读。

二.缺点

空间换时间,写的时候内存里会出现一模一样的副本,对内存消耗大。通过数组副本可以保证大量的读不需要和写互斥。如果数组很大,可能要考虑内存占用会是数组大小的几倍。此外使用数组副本来统计数据,会存在统计数据不一致的问题。

三.使用场景

适用于读多写少的场景,这样大量的读操作不会被写操作影响,而且不要求统计数据具有实时性。

2.并发安全的链表队列ConcurrentLinkedQueue

(1)ConcurrentLinkedQueue的介绍

(2)ConcurrentLinkedQueue的构造方法

(3)ConcurrentLinkedQueue的offer()方法

(4)ConcurrentLinkedQueue的poll()方法

(5)ConcurrentLinkedQueue的peak()方法

(6)ConcurrentLinkedQueue的size()方法

(1)ConcurrentLinkedQueue的介绍

ConcurrentLinkedQueue是一种并发安全且非阻塞的链表队列(无界队列)。

ConcurrentLinkedQueue采用CAS机制来保证多线程操作队列时的并发安全。

链表队列会采用先进先出的规则来对结点进行排序。每次往链表队列添加元素时,都会添加到队列的尾部。每次需要获取元素时,都会直接返回队列头部的元素。

并发安全的HashMap是ConcurrentHashMap

并发安全的ArrayList是CopyOnWriteArrayList

并发安全的LinkedList是ConcurrentLinkedQueue

(2)ConcurrentLinkedQueue的构造方法

ConcurrentLinkedQueue是基于链表实现的,链表结点为其内部类Node。

ConcurrentLinkedQueue的构造方法会初始化链表的头结点和尾结点为同一个值为null的Node对象。

Node结点通过next指针指向下一个Node结点,从而组成一个单向链表。而ConcurrentLinkedQueue的head和tail两个指针指向了链表的头和尾结点。

public class ConcurrentLinkedQueueDemo {public static void main(String[] args) {ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<String>();queue.offer("张三");//向队尾添加元素queue.offer("李四");//向队尾添加元素queue.offer("王五");//向队尾添加元素System.out.println(queue.peek());//返回队头的元素不出队System.out.println(queue.poll());//返回队头的元素而且出队System.out.println(queue.peek());//返回队头的元素不出队}
}//An unbounded thread-safe queue based on linked nodes.
//This queue orders elements FIFO (first-in-first-out).
//The head of the queue is that element that has been on the queue the longest time.
//The tail of the queue is that element that has been on the queue the shortest time. 
//New elements are inserted at the tail of the queue, 
//and the queue retrieval operations obtain elements at the head of the queue.
//A ConcurrentLinkedQueue is an appropriate choice when many threads will share access to a common collection. 
//Like most other concurrent collection implementations, this class does not permit the use of null elements.
public class ConcurrentLinkedQueue<E> extends AbstractQueue<E> implements Queue<E>, java.io.Serializable {...private transient volatile Node<E> head;private transient volatile Node<E> tail;//构造方法,初始化链表队列的头结点和尾结点为同一个值为null的Node对象//Creates a ConcurrentLinkedQueue that is initially empty.public ConcurrentLinkedQueue() {head = tail = new Node<E>(null);}private static class Node<E> {volatile E item;volatile Node<E> next;private static final sun.misc.Unsafe UNSAFE;private static final long itemOffset;private static final long nextOffset;static {try {UNSAFE = sun.misc.Unsafe.getUnsafe();Class<?> k = Node.class;itemOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("item"));nextOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("next"));} catch (Exception e) {throw new Error(e);}}Node(E item) {UNSAFE.putObject(this, itemOffset, item);}boolean casItem(E cmp, E val) {return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);}void lazySetNext(Node<E> val) {UNSAFE.putOrderedObject(this, nextOffset, val);}boolean casNext(Node<E> cmp, Node<E> val) {return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);}}...
}

(3)ConcurrentLinkedQueue的offer()方法

其中关键的代码就是"p.casNext(null, newNode))",就是把p的next指针由原来的指向空设置为指向新的结点,并且通过CAS确保同一时间只有一个线程可以成功执行这个操作。

注意:更新tail指针并不是实时更新的,而是隔一个结点再更新。这样可以减少CAS指令的执行次数,从而降低CAS操作带来的性能影响。

图片

插入第一个元素后,tail指针指向倒数第二个节点。

插入第二个元素后,tail指针指向最后一个节点。

插入第三个元素后,tail指针指向倒数第二个节点。

插入第四个元素后,tail指针指向最后一个节点。

//An unbounded thread-safe queue based on linked nodes.
public class ConcurrentLinkedQueue<E> extends AbstractQueue<E> implements Queue<E>, java.io.Serializable {...private transient volatile Node<E> head;private transient volatile Node<E> tail;private static final sun.misc.Unsafe UNSAFE;private static final long headOffset;private static final long tailOffset;static {try {UNSAFE = sun.misc.Unsafe.getUnsafe();Class<?> k = ConcurrentLinkedQueue.class;headOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("head"));tailOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("tail"));} catch (Exception e) {throw new Error(e);}}//构造方法,初始化链表队列的头结点和尾结点为同一个值为null的Node对象//Creates a ConcurrentLinkedQueue that is initially empty.public ConcurrentLinkedQueue() {head = tail = new Node<E>(null);}public boolean offer(E e) {checkNotNull(e);final Node<E> newNode = new Node<E>(e);//插第一个元素时, tail和head都是初始化时的空节点, p也指向该空节点, q是该空节点的next元素;//很明显q是null, p.casNext后, p的next设为第一个元素, 此时p和t相等, tail的next是第一个元素;//由于p==t, 于是返回true, head和tail还是指向初始化时的空节点, tail指针指向的是倒数第二个节点;//插第二个元素时, q成为第一个元素,不为null了, 而且p指向tail, tail的next是第一个元素, 所以p != q;//由于此时p和t还是一样的, 所以会将q赋值给p, 也就是p指向第一个元素了, 再次进行新一轮循环;//新一轮循环时, q指向第一个元素的next成为null, 所以会对第一个元素执行casNext操作;//也就是将第二个元素设为第一个元素的next, 设完后由于p和t不相等了, 会执行casTail设第二个元素为tail;//插入第三个元素时, 又会和插入第一个元素一样了, 这时tail指针指向的是倒数第二个节点;//插入第四个元素时, 和插入第二个元素一样, 这是tail指针指向的是最后一个节点;for (Node<E> t = tail, p = t;;) {Node<E> q = p.next;//p是尾结点,q是尾结点的下一个结点if (q == null) {//插入第一个元素时执行的代码if (p.casNext(null, newNode)) {//将新结点设置为尾结点的下一个结点if (p != t) {//隔一个结点再CAS更新tail指针casTail(t, newNode);}return true;}} else if (p == q) {p = (t != (t = tail)) ? t : head;} else {//插入第二个元素时执行的代码p = (p != t && t != (t = tail)) ? t : q;}}}private boolean casTail(Node<E> cmp, Node<E> val) {return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);}...
}

(4)ConcurrentLinkedQueue的poll()方法

poll()方法会将链表队列的头结点出队。

注意:更新head指针时也不是实时更新的,而是隔一个结点再更新。这样可以减少CAS指令的执行次数,从而降低CAS操作带来的性能影响。

//An unbounded thread-safe queue based on linked nodes.
public class ConcurrentLinkedQueue<E> extends AbstractQueue<E> implements Queue<E>, java.io.Serializable {...private transient volatile Node<E> head;private transient volatile Node<E> tail;private static final sun.misc.Unsafe UNSAFE;private static final long headOffset;private static final long tailOffset;static {try {UNSAFE = sun.misc.Unsafe.getUnsafe();Class<?> k = ConcurrentLinkedQueue.class;headOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("head"));tailOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("tail"));} catch (Exception e) {throw new Error(e);}}//构造方法,初始化链表队列的头结点和尾结点为同一个值为null的Node对象//Creates a ConcurrentLinkedQueue that is initially empty.public ConcurrentLinkedQueue() {head = tail = new Node<E>(null);}public E poll() {restartFromHead:for (;;) {for (Node<E> h = head, p = h, q;;) {E item = p.item;if (item != null && p.casItem(item, null)) {if (p != h) {//隔一个结点才CAS更新head指针updateHead(h, ((q = p.next) != null) ? q : p);}return item;} else if ((q = p.next) == null) {updateHead(h, p);return null;} else if (p == q) {continue restartFromHead;} else {p = q;}}}}final void updateHead(Node<E> h, Node<E> p) {if (h != p && casHead(h, p)) {h.lazySetNext(h);}}private boolean casHead(Node<E> cmp, Node<E> val) {return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);}...
}

(5)ConcurrentLinkedQueue的peak()方法

peek()方法会获取链表的头结点,但是不会出队。

//An unbounded thread-safe queue based on linked nodes.
public class ConcurrentLinkedQueue<E> extends AbstractQueue<E> implements Queue<E>, java.io.Serializable {...private transient volatile Node<E> head;public E peek() {restartFromHead:for (;;) {for (Node<E> h = head, p = h, q;;) {E item = p.item;if (item != null || (q = p.next) == null) {updateHead(h, p);return item;} else if (p == q) {continue restartFromHead;} else {p = q;}}}}final void updateHead(Node<E> h, Node<E> p) {if (h != p && casHead(h, p)) {h.lazySetNext(h);}}private boolean casHead(Node<E> cmp, Node<E> val) {return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);}...
}

(6)ConcurrentLinkedQueue的size()方法

size()方法主要用来返回链表队列的大小,查看链表队列有多少个元素。size()方法不会加锁,会直接从头节点开始遍历链表队列中的每个结点。

//An unbounded thread-safe queue based on linked nodes.
public class ConcurrentLinkedQueue<E> extends AbstractQueue<E> implements Queue<E>, java.io.Serializable {...public int size() {int count = 0;for (Node<E> p = first(); p != null; p = succ(p))if (p.item != null) {if (++count == Integer.MAX_VALUE) {break;}}}return count;}//Returns the first live (non-deleted) node on list, or null if none.//This is yet another variant of poll/peek; here returning the first node, not element.//We could make peek() a wrapper around first(), but that would cost an extra volatile read of item,//and the need to add a retry loop to deal with the possibility of losing a race to a concurrent poll(). Node<E> first() {restartFromHead:for (;;) {for (Node<E> h = head, p = h, q;;) {boolean hasItem = (p.item != null);if (hasItem || (q = p.next) == null) {updateHead(h, p);return hasItem ? p : null;} else if (p == q) {continue restartFromHead;} else {p = q;}}}}//Returns the successor of p, or the head node if p.next has been linked to self, //which will only be true if traversing with a stale pointer that is now off the list.final Node<E> succ(Node<E> p) {Node<E> next = p.next;return (p == next) ? head : next;}...
}

如果在遍历的过程中,有线程执行入队或者是出队的操作,此时会怎样?

从队头开始遍历,遍历到一半时:如果有线程在队列尾部进行入队操作,此时的遍历能及时看到新添加的元素。因为入队操作就是设置队列尾部节点的next指针指向新添加的结点,而入队时设置next指针属于volatile写,因此遍历时是可以看到的。如果有线程从队列头部进行出队操作,此时的遍历则无法感知有元素出队了。

所以可以总结出这些并发安全的集合:ConcurrentHashMap、CopyOnWriteArrayList和ConcurrentLinkedQueue,为了优化多线程下的并发性能,会牺牲掉统计数据的一致性。为了保证多线程写的高并发性能,会大量采用CAS进行无锁化操作。同时会让很多读操作比如常见的size()操作,不使用锁。因此使用这些并发安全的集合时,要考虑并发下的统计数据的不一致问题。

3.并发编程中的阻塞队列概述

(1)什么是阻塞队列

(2)阻塞队列提供的方法

(3)阻塞队列的应用

(1)什么是阻塞队列

队列是一种只允许在一端进行移除操作、在另一端进行插入操作的线性表,队列中允许插入的一端称为队尾,允许移除的一端称为队头。

阻塞队列就是在队列的基础上增加了两个操作:

一.支持阻塞插入

在队列满时会阻塞继续往队列中添加数据的线程,直到队列中有元素被释放。

二.支持阻塞移除

在队列空时会阻塞从队列中获取元素的线程,直到队列中添加了新的元素。

阻塞队列其实实现了一个生产者/消费者模型:生产者往队列中添加数据,消费者从队列中获取数据。队列满了阻塞生产者,队列空了阻塞消费者。

阻塞队列中的元素可能会使用数组或者链表等来进行存储。一个队列中能容纳多少个元素取决于队列的容量大小,因此阻塞队列也分为有界队列和无界队列。

有界队列指有固定大小的队列,无界队列指没有固定大小的队列。实际上无界队列也是有大小限制的,只是大小限制为非常大,可认为无界。

注意:在无界队列中,由于理论上不存在队列满的情况,所以不存在阻塞。

阻塞队列在很多地方都会用到,比如线程池、ZooKeeper。一般使用阻塞队列来实现生产者/消费者模型。

(2)阻塞队列提供的方法

阻塞队列的操作有插入、移除、检查,在队列满或者空时会有不同的效果。

一.抛出异常

当队列满的时候通过add(e)方法添加元素,会抛出异常。

当队列空的时候调用remove(e)方法移除元素,也会抛出异常。

二.返回特殊值

调用offer(e)方法向队列入队元素时,会返回添加结果true或false。

调用poll()方法从队列出队元素时,会从队列取出一个元素或null。

三.一直阻塞

在队列满了的情况下,调用插入方法put(e)向队列中插入元素时,队列会阻塞插入元素的线程,直到队列不满或者响应中断才退出阻塞。

在队列空了的情况下,调用移除方法take()从队列移除元素时,队列会阻塞移除元素的线程,直到队列不为空时唤醒线程。

四.超时退出

超时退出其实就是在offer()和poll()方法中增加了阻塞的等待时间。

图片

(3)阻塞队列的应用

阻塞队列可以理解为线程级别的消息队列。

消息中间件可以理解为进程级别的消息队列。

所以可以通过阻塞队列来缓存线程的请求,从而达到流量削峰的目的。

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

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

相关文章

量子计算驱动的金融衍生品定价革命:突破传统蒙特卡洛模拟的性能边界

引言&#xff1a;金融计算的算力困局 某国际投行采用128量子位处理器对亚洲期权组合定价时&#xff0c;其量子振幅估计算法在2.7秒内完成传统GPU集群需要68小时的计算任务。在蒙特卡洛路径模拟实验中&#xff0c;量子随机游走算法将10,000维衍生品的价格收敛速度提升4个数量级…

hive—常用的函数整理

1、size(split(...))函数用于计算分割后字符串数组的长度 实例1&#xff09;&#xff1a;由客户编号列表计算客户编号个数 --数据准备 with tmp_test01 as ( select tag074445270 tag_id,202501busi_mon , 012399931003,012399931000 index_val union all select tag07444527…

国产编辑器EverEdit - 如何在EverEdit中管理工程?

1 工程管理 1.1 应用场景 用户创建工程后&#xff0c;会涉及到工程的管理 &#xff0c;比如&#xff1a;打开工程、关闭工程等 1.2 使用方法 1.2.1 打开工程 单击主菜单工程 -> 打开工程&#xff0c;会弹出打开对话框&#xff0c;用户在对话框中选择需要打开的工程文件即…

MYSQL-数据库-DDL-DML-DQL-DCL-基础学习

MySql概念&#xff1a; 建立在关系模型基础上&#xff0c;有多张相互连接的二维表组成的数据库 SQL通用语法&#xff1a; 1.SQL语句可以单行或多行书写&#xff0c;以分号结尾 2.SQL语句可以使用空格/缩进来增强语句的可读性 3.MySQL数据库的SQL语句不区分大小写&#xff0c;关…

SpringBoot核心框架之AOP详解

SpringBoot核心框架之AOP详解 一、AOP基础 1.1 AOP概述 AOP&#xff1a;Aspect Oriented Programming&#xff08;面向切面编程&#xff0c;面向方面编程&#xff09;&#xff0c;其实就是面向特定方法编程。 场景&#xff1a;项目部分功能运行较慢&#xff0c;定位执行耗时…

低代码与开发框架的一些整合[2]

1.分析的项目资源说明 经过近期的的不断分析与运行对比&#xff0c;最终把注意力集中在了以下几个框架&#xff1a; 01.dibootdiboot.diboot: 写的更少, 性能更好 -> 为开发人员打造的低代码开发平台。Mybatis-plus关联查询&#xff0c;关联无SQL&#xff0c;性能高10倍&a…

Spring Boot 中事务的用法详解

引言 在 Spring Boot 中&#xff0c;事务管理是一个非常重要的功能&#xff0c;尤其是在涉及数据库操作的业务场景中。Spring 提供了强大的事务管理支持&#xff0c;能够帮助我们简化事务的管理和控制。本文将详细介绍 Spring Boot 中事务的用法&#xff0c;包括事务的基本概…

Java面试——Tomcat

优质博文&#xff1a;IT_BLOG_CN 一、Tomcat 顶层架构 Tomcat中最顶层的容器是Server&#xff0c;代表着整个服务器&#xff0c;从上图中可以看出&#xff0c;一个Server可以包含至少一个Service&#xff0c;用于具体提供服务。Service主要包含两个部分&#xff1a;Connector和…

第4章 信息系统架构(三)

4.3 应用架构 应用架构的主要内容是规划出目标应用分层分域架构&#xff0c;根据业务架构规划目标应用域、应用组和目标应用组件&#xff0c;形成目标应用架构逻辑视图和系统视图。从功能视角出发&#xff0c;阐述应用组件各自及应用架构整体上&#xff0c;如何实现组织的高阶…

python小项目编程-中级(1、图像处理)

目录 图像处理 实现 测试 unittest pytest 图像处理 实现界面化操作&#xff0c;使用PIL库实现简单的图像处理功能&#xff0c;如缩放&#xff08;设置缩放比例&#xff09;、旋转和滤镜、对比度调整、亮度调整、灰度图、二值化图&#xff08;二值图如果使用的是彩色图片需…

2025 WE DAY品牌日| 天璇II WE X7 Pro充电桩震撼发布,能效电气开启充电革命

随着新能源产业的迅猛发展,充电桩作为电动汽车能量补给的重要基础设施,正在成为市场关注的焦点。能效电气作为充电桩领域的佼佼者,专注于研发高效、智能的充电解决方案,为电动汽车的普及与可持续发展铺设了坚实的基础。 2025年2月21日,能效电气在深圳盛大举办了以“以创新 引未…

< OS 有关 > Ubuntu 24 SSH 服务器更换端口 in jp/us VPSs

原因&#xff1a; 两台 VPS 的 ssh 端口一直被密码重试&#xff0c; us 这台已经封了 632, jp 这台两周前清过一次 sqlite3 数据&#xff0c;现在赞到 1008 Fail2Ban 是使用 sqlite3 来记录&#xff0c;数据量大后&#xff0c;硬盘的 I/O 会飙升&#xff0c;我有写过一个 app…

MATLAB学习之旅:数据插值与曲线拟合

在MATLAB的奇妙世界里,我们已经走过了一段又一段的学习旅程。从基础的语法和数据处理,到如今,我们即将踏入数据插值与曲线拟合这片充满魅力的领域。这个领域就像是魔法中的艺术创作,能够让我们根据现有的数据点,构建出更加丰富的曲线和曲面,从而更好地理解和描述数据背后…

若依-@Excel新增注解numberFormat

Excel注解中原本的scale会四舍五入小数&#xff0c;导致进度丢失 想要的效果 显示的时候保留两个小数真正的数值是保留之前的数值 还原过程 若以中有一個專門的工具类&#xff0c;用来处理excel的 找到EXCEL导出方法exportExcel()找到writeSheet,写表格的方法找到填充数据的方法…

LeetCode 热题 100_搜索二维矩阵(64_74_中等_C++)(二分查找)(暴力破解法;Z字形查找;一次二分查找)

LeetCode 热题 100_搜索二维矩阵&#xff08;64_74&#xff09; 题目描述&#xff1a;输入输出样例&#xff1a;题解&#xff1a;解题思路&#xff1a;思路一&#xff08;暴力破解法&#xff09;&#xff1a;思路二&#xff08;Z字形查找&#xff09;&#xff1a;思路三&#x…

新手小白如何挖掘cnvd通用漏洞之存储xss漏洞(利用xss钓鱼)

视频教程和更多福利在我主页简介或专栏里 &#xff08;不懂都可以来问我 专栏找我哦&#xff09; 如果对你有帮助你可以来专栏找我&#xff0c;我可以无偿分享给你对你更有帮助的一些经验和资料哦 目录&#xff1a; 一、XSS的三种类型&#xff1a; 二、XSS攻击的危害&#x…

Python开源项目月排行 2024年12月

#2024年12月2025年1月21日1DeepSeek-Coder-V2一个开源的专家混合&#xff08;MoE&#xff09;代码语言模型&#xff0c;其在代码特定任务中的性能可与GPT4-Turbo相媲美。具体而言&#xff0c;DeepSeek-Coder-V2是在DeepSeek-V2的一个中间检查点上进一步预训练的&#xff0c;增加…

Resource not found: roslaunchROS path [0]=/opt/ros/noetic/share/ros

解决办法&#xff1b; cd ~/catkin_ws rm -rf build/ devel/ catkin_make source devel/setup.bash sudo apt-get install ros-noetic-roslaunch 输入roscore后

.NET + Vue3 的前后端项目在IIS的发布

目录 一、发布准备 1、安装 IIS 2、安装 Windows Hosting Bundle&#xff08;.NET Core 托管捆绑包&#xff09; 3、安装 IIS URL Rewrite 二、项目发布 1、后端项目发布 2、前端项目发布 3、将项目部署到 IIS中 三、网站配置 1、IP配置 2、防火墙配置 3、跨域配置…

Linux驱动开发之音频驱动与基础应用编程

目录 CODEC芯片 音频编码 I2S总线接口 数字音频接口(DAI) 设备树配置 ALSA 音频相关概念 应用程序编写 运行测试 CODEC芯片 音频若想被CPU“听到”&#xff0c;就必须转换为CPU能够“听懂”的语言&#xff0c;即二进制数据的0和1。在信号处理领域&#xff0c;声音是模…