看图学源码 之 Atomic 类源码浅析一(cas + 自旋操作的 AtomicXXX原子类)

Atomic

针对基本数据类型的单个变量

AtomicInteger
// 就是对  value 执行操作
public class AtomicInteger extends Number implements java.io.Serializable {...// 拿到 Unsafe  类  private static final Unsafe unsafe = Unsafe.getUnsafe();// 偏移量: 字段相对于对象内存地址的偏移量private static final long valueOffset;static {try {// 反射的方式获取 value 的偏移量  这个偏移量可以用于后续的无锁操作valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));} catch (Exception ex) { throw new Error(ex); }}private volatile int value;// 其他的方法都是直接调用 native 的方法实现的,如:getAndIncrement、getAndDecrement、compareAndSet、getAndSet等...// 以此为例/*如果指定位置上的当前值==预期值,则自动将该值设置为给定的更新值。形参:expect期望值 update ——新值返回值:如果cas 成功则为true 。返回 False 表示指定位置上的实际值不等于期望值。*/public final boolean compareAndSet(int expect, int update) {return unsafe.compareAndSwapInt(this, valueOffset, expect, update);}}
AtomicBoolean
public class AtomicBoolean implements java.io.Serializable {...// setup to use Unsafe.compareAndSwapInt for updatesprivate static final Unsafe unsafe = Unsafe.getUnsafe();private static final long valueOffset;static {try {valueOffset = unsafe.objectFieldOffset(AtomicBoolean.class.getDeclaredField("value"));} catch (Exception ex) { throw new Error(ex); }}private volatile int value;...//如果当前值==预期值,则自动将该值设置为给定的更新值。public final boolean compareAndSet(boolean expect, boolean update) {  // 这里的是 boolean 类型的值// 将boolean   转为 int  值进行 cas int e = expect ? 1 : 0;int u = update ? 1 : 0;return unsafe.compareAndSwapInt(this, valueOffset, e, u);}
}
AtomicLong
public class  AtomicLong extends Number implements java.io.Serializable {private static final long serialVersionUID = 1927816293512124184L;// setup to use Unsafe.compareAndSwapLong for updatesprivate static final Unsafe unsafe = Unsafe.getUnsafe();private static final long valueOffset;/*** 记录底层 JVM 是否支持 long 的无锁compareAndSwap。虽然 Unsafe.compareAndSwapLong 方法在任一情况下都有效,但应在 Java 级别处理某些构造以避免锁定用户可见的锁。*/static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();/**返回底层 JVM 是否支持 long 的无锁 CompareAndSet。仅调用一次并缓存在 VM_SUPPORTS_LONG_CAS 中。*/private static native boolean VMSupportsCS8();static {try {valueOffset = unsafe.objectFieldOffset(AtomicLong.class.getDeclaredField("value"));} catch (Exception ex) { throw new Error(ex); }}private volatile long value;.../* 如果当前值==预期值,则自动将该值设置为给定的更新值。形参:expect期望值 update ——新值返回值:如果成功则为true 。返回 False 表示实际值不等于期望值。*/public final boolean compareAndSet(long expect, long update) {return unsafe.compareAndSwapLong(this, valueOffset, expect, update);} ... 
}

针对引用类型的单个变量

通过对 Object中的属性进行反射 + CAS 支持属性原子操作

AtomicReference
public class AtomicReference<V> implements java.io.Serializable {private static final long serialVersionUID = -1848883965231344442L;private static final Unsafe unsafe = Unsafe.getUnsafe();private static final long valueOffset;static {try {valueOffset = unsafe.objectFieldOffset(AtomicReference.class.getDeclaredField("value"));} catch (Exception ex) { throw new Error(ex); }}private volatile V value;...public final boolean compareAndSet(V expect, V update) {return unsafe.compareAndSwapObject(this, valueOffset, expect, update);}...
}
AtomicStampedReference
public class AtomicStampedReference<V> {private static class Pair<T> {final T reference;final int stamp;   // 解决了 cas 的 ABA 问题private Pair(T reference, int stamp) {this.reference = reference;this.stamp = stamp;}static <T> Pair<T> of(T reference, int stamp) {return new Pair<T>(reference, stamp);}}private volatile Pair<V> pair;.../*如果当前引用==到预期引用并且当前标记等于预期标记,则以原子方式将引用和标记的值设置为给定更新值。形参:expectedReference – 参考的预期值newReference – 参考的新值expectedStamp – 邮票的预期值newStamp – 邮票的新值返回值:如果成功则为true*/public boolean compareAndSet(V   expectedReference,V   newReference,int expectedStamp,int newStamp) {// 将当前的pair赋值给变量currentPair<V> current = pair;returnexpectedReference == current.reference && //当前的值是 预期的值expectedStamp == current.stamp && // 当前的stamp 也是预期的值((newReference == current.reference && // 新值是 当前的值newStamp == current.stamp) ||  // stamp 的值是 当前的值//前两个都是false 那么就 cas 的 将current替换为Pair.of(newReference, newStamp)casPair(current, Pair.of(newReference, newStamp)));}.../*使用CAS操作来原子性地更新AtomicStampedReference对象中的pair字段的值。*/// 获取了一个用于执行底层操作的Unsafe实例。private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();//获取了pair字段在AtomicStampedReference类中的偏移量。
private static final long pairOffset = objectFieldOffset(UNSAFE, "pair", AtomicStampedReference.class);// 使用UNSAFE.compareAndSwapObject方法来比较并交换对象的pair字段的值。如果当前的pair字段的值等于cmp,则将其更新为val并返回true,否则返回false。private boolean casPair(Pair<V> cmp, Pair<V> val) {return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);}//获取指定类中指定字段的偏移量。static long objectFieldOffset(sun.misc.Unsafe UNSAFE,String field, Class<?> klazz) {try {//通过反射获取字段对象,然后使用UNSAFE.objectFieldOffset方法获取字段的偏移量。return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));} catch (NoSuchFieldException e) {// 如果字段不存在,则抛出NoSuchFieldError异常。NoSuchFieldError error = new NoSuchFieldError(field);error.initCause(e);throw error;}}
}
AtomicMarkableReference
public class AtomicMarkableReference<V> {private static class Pair<T> {final T reference;final boolean mark;private Pair(T reference, boolean mark) {this.reference = reference;this.mark = mark;}static <T> Pair<T> of(T reference, boolean mark) {return new Pair<T>(reference, mark);}}private volatile Pair<V> pair;.../*如果当前引用==到预期引用并且当前标记等于预期标记,则以原子方式将引用和标记的值设置为给定更新值。形参:expectedReference – 参考的预期值 newReference – 参考的新值 expectedMark – 标记的期望值 newMark – 标记的新值返回值:如果成功则为true*/public boolean compareAndSet(V       expectedReference,V       newReference,boolean expectedMark,boolean newMark) {Pair<V> current = pair;returnexpectedReference == current.reference &&expectedMark == current.mark &&((newReference == current.reference &&newMark == current.mark) ||casPair(current, Pair.of(newReference, newMark)));}...private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();private static final long pairOffset =objectFieldOffset(UNSAFE, "pair", AtomicMarkableReference.class);private boolean casPair(Pair<V> cmp, Pair<V> val) {return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);}static long objectFieldOffset(sun.misc.Unsafe UNSAFE,String field, Class<?> klazz) {try {return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));} catch (NoSuchFieldException e) {// Convert Exception to corresponding ErrorNoSuchFieldError error = new NoSuchFieldError(field);error.initCause(e);throw error;}}
}

针对的是多个变量

都是通过下标去操作数组中的元素

AtomicIntegerArray
public class AtomicIntegerArray implements java.io.Serializable {private static final long serialVersionUID = 2862133569453604235L;private static final Unsafe unsafe = Unsafe.getUnsafe();private static final int base = unsafe.arrayBaseOffset(int[].class);private static final int shift;private final int[] array;// 计算int数组的元素大小,并确定位移量static {// 使用unsafe.arrayIndexScale(int[].class)函数获取int数组元素的大小,存储在变量scale中。int scale = unsafe.arrayIndexScale(int[].class);// 它通过检查scale是否是2的幂次方来确保元素大小是2的幂次方。如果不是,就会抛出一个错误。if ((scale & (scale - 1)) != 0)throw new Error("data type scale not a power of two");// 31 - Integer.numberOfLeadingZeros(scale)函数计算scale的二进制表示中前导零的数量,// 得到位移量,并将结果存储在shift变量中。shift = 31 - Integer.numberOfLeadingZeros(scale);}.../*如果当前值==预期值,则自动将位置i处的元素设置为给定的更新值。形参:i – 索引   expect期望值 update ——新值返回值:如果成功则为true 。返回 False 表示实际值不等于期望值。*/public final boolean compareAndSet(int i, int expect, int update) {return compareAndSetRaw(checkedByteOffset(i), expect, update);}private boolean compareAndSetRaw(long offset, int expect, int update) {return unsafe.compareAndSwapInt(array, offset, expect, update);}//接受一个整数参数i,并返回一个长整型值。private long checkedByteOffset(int i) {
//检查参数i是否小于0或大于等于数组array的长度。如果是,则抛出一个IndexOutOfBoundsException异常,异常信息中包含索引i的值。if (i < 0 || i >= array.length)throw new IndexOutOfBoundsException("index " + i);//调用 byteOffset(i) 来计算并返回字节偏移量return byteOffset(i);}// 将整数 i 左移 shift 位,并将结果与变量 base 相加,然后将其转换为长整型值返回private static long byteOffset(int i) {return ((long) i << shift) + base;}...
}
AtomicLongArray
public class AtomicLongArray implements java.io.Serializable {private static final long serialVersionUID = -2308431214976778248L;private static final Unsafe unsafe = Unsafe.getUnsafe();private static final int base = unsafe.arrayBaseOffset(long[].class);private static final int shift;private final long[] array;static {int scale = unsafe.arrayIndexScale(long[].class);if ((scale & (scale - 1)) != 0)throw new Error("data type scale not a power of two");shift = 31 - Integer.numberOfLeadingZeros(scale);}private long checkedByteOffset(int i) {if (i < 0 || i >= array.length)throw new IndexOutOfBoundsException("index " + i);return byteOffset(i);}private static long byteOffset(int i) {return ((long) i << shift) + base;}/*如果当前值==预期值,则自动将位置i处的元素设置为给定的更新值。形参:i – 索引 expect期望值 update ——新值返回值:如果成功则为true 。返回 False 表示实际值不等于期望值。*/ public final boolean compareAndSet(int i, long expect, long update) {return compareAndSetRaw(checkedByteOffset(i), expect, update);}private boolean compareAndSetRaw(long offset, long expect, long update) {return unsafe.compareAndSwapLong(array, offset, expect, update);}...
}
AtomicReferenceArray
public class AtomicReferenceArray<E> implements java.io.Serializable {private static final long serialVersionUID = -6209656149925076980L;private static final Unsafe unsafe;private static final int base;private static final int shift;private static final long arrayFieldOffset;private final Object[] array; // must have exact type Object[]// 获取一些与数组操作相关的参数,并进行初始化static {try {// 通过 Unsafe.getUnsafe() 方法获取一个 Unsafe 对象的实例,并将其赋值给静态变量 unsafe。unsafe = Unsafe.getUnsafe();// 使用 unsafe.objectFieldOffset() 方法获取 AtomicReferenceArray 类中名为 "array" 的字段的偏移量,并将其赋值给静态变量 arrayFieldOffset。
arrayFieldOffset = unsafe.objectFieldOffset(AtomicReferenceArray.class.getDeclaredField("array"));// 使用 unsafe.arrayBaseOffset() 方法获取 Object[] 类的基本偏移量,并将其赋值给静态变量 base。base = unsafe.arrayBaseOffset(Object[].class);//  使用 unsafe.arrayIndexScale() 方法获取 Object[] 类的索引缩放因子,并将其赋值给局部变量 scale。int scale = unsafe.arrayIndexScale(Object[].class);// 如果 scale 不是 2 的幂次方,则抛出一个 异常if ((scale & (scale - 1)) != 0)throw new Error("data type scale not a power of two");// 根据 scale 计算 shift 的值,该值表示 scale 的二进制表示中最高位的索引。shift = 31 - Integer.numberOfLeadingZeros(scale);} catch (Exception e) {throw new Error(e);}}/*如果当前值==预期值,则自动将位置i处的元素设置为给定的更新值。形参:i – 索引 expect期望值 update ——新值返回值:如果成功则为true 。返回 False 表示实际值不等于期望值。*/private long checkedByteOffset(int i) {if (i < 0 || i >= array.length)throw new IndexOutOfBoundsException("index " + i);return byteOffset(i);}private static long byteOffset(int i) {return ((long) i << shift) + base;}...public final boolean compareAndSet(int i, E expect, E update) {return compareAndSetRaw(checkedByteOffset(i), expect, update);}private boolean compareAndSetRaw(long offset, E expect, E update) {return unsafe.compareAndSwapObject(array, offset, expect, update);}...
}

针对对象类型中的某个属性

AtomicIntegerFieldUpdater
public abstract class AtomicIntegerFieldUpdater<T> {@CallerSensitivepublic static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {return new AtomicIntegerFieldUpdaterImpl<U>(tclass, fieldName, Reflection.getCallerClass());}/*如果当前值==预期值,则自动将此更新程序管理的给定对象的字段设置为给定的更新值。该方法相对于对compareAndSet和set其他调用而言保证是原子的,但不一定相对于字段中的其他更改。形参:obj – 要有条件设置其字段的对象 expect期望值 update ——新值返回值:如果成功则为true转发: ClassCastException – 如果obj不是拥有构造函数中建立的字段的类的实例*/public abstract boolean compareAndSet(T obj, int expect, int update);private static final class AtomicIntegerFieldUpdaterImpl<T> extends AtomicIntegerFieldUpdater<T> {private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();private final long offset;private final Class<?> cclass;private final Class<T> tclass;// 通过反射获取指定类中的整型字段,并创建一个AtomicIntegerFieldUpdater对象来实现对该字段的原子性更新操作AtomicIntegerFieldUpdaterImpl(final Class<T> tclass,final String fieldName,final Class<?> caller) {final Field field;final int modifiers;try {// 代码通过反射获取了要更新的字段对象,这个字段是在指定的类(tclass)中通过字段名(fieldName)来获取的field = AccessController.doPrivileged(new PrivilegedExceptionAction<Field>() {public Field run() throws NoSuchFieldException {return tclass.getDeclaredField(fieldName);}});// 检查字段的修饰符(modifiers)来确保它是volatile类型,并且字段的类型是int类型,否则会抛出异常。modifiers = field.getModifiers();//检查字段的访问权限。如果字段是protected字段,并且访问者(caller)是tclass的子类或者包内的类,那么将使用caller作为访问者,否则使用tclass作为访问者。sun.reflect.misc.ReflectUtil.ensureMemberAccess(caller, tclass, null, modifiers);ClassLoader cl = tclass.getClassLoader();ClassLoader ccl = caller.getClassLoader();if ((ccl != null) && (ccl != cl) &&((cl == null) || !isAncestor(cl, ccl))) {sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);}} catch (PrivilegedActionException pae) {throw new RuntimeException(pae.getException());} catch (Exception ex) {throw new RuntimeException(ex);}if (field.getType() != int.class)throw new IllegalArgumentException("Must be integer type");if (!Modifier.isVolatile(modifiers))throw new IllegalArgumentException("Must be volatile type");// 对受保护字段成员的访问仅限于访问类或其子类之一的接收者,并且访问类又必须是受保护成员的定义类的子类(或包兄弟)。如果更新程序引用当前包外部的声明类的受保护字段,则接收者参数将缩小为访问类的类型。this.cclass = (Modifier.isProtected(modifiers) &&tclass.isAssignableFrom(caller) &&!isSamePackage(tclass, caller))? caller : tclass;this.tclass = tclass;//使用UNSAFE.objectFieldOffset(field)方法获取字段的偏移量,并将其保存在offset字段中,以便后续的原子性更新操作中使用。this.offset = U.objectFieldOffset(field);}public final boolean compareAndSet(T obj, int expect, int update) {accessCheck(obj);return U.compareAndSwapInt(obj, offset, expect, update);}//检查目标参数是否是 cclass 的实例。失败时,抛出原因。private final void accessCheck(T obj) {if (!cclass.isInstance(obj))throwAccessCheckException(obj);}//如果 accessCheck 由于受保护的访问而失败,则抛出访问异常,否则抛出 ClassCastException。private final void throwAccessCheckException(T obj) {if (cclass == tclass)throw new ClassCastException();elsethrow new RuntimeException(new IllegalAccessException("Class " +cclass.getName() +" can not access a protected member of class " +tclass.getName() +" using an instance of " +obj.getClass().getName()));}}
}
AtomicLongFieldUpdater
public abstract class AtomicLongFieldUpdater<T> {@CallerSensitivepublic static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass,String fieldName) {Class<?> caller = Reflection.getCallerClass();if (AtomicLong.VM_SUPPORTS_LONG_CAS)return new CASUpdater<U>(tclass, fieldName, caller);elsereturn new LockedUpdater<U>(tclass, fieldName, caller);}public abstract boolean compareAndSet(T obj, long expect, long update);private static final class CASUpdater<T> extends AtomicLongFieldUpdater<T> {private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();private final long offset;private final Class<?> cclass;private final Class<T> tclass;CASUpdater(final Class<T> tclass, final String fieldName,final Class<?> caller) {final Field field;final int modifiers;try {field = AccessController.doPrivileged(new PrivilegedExceptionAction<Field>() {public Field run() throws NoSuchFieldException {return tclass.getDeclaredField(fieldName);}});modifiers = field.getModifiers();sun.reflect.misc.ReflectUtil.ensureMemberAccess(caller, tclass, null, modifiers);ClassLoader cl = tclass.getClassLoader();ClassLoader ccl = caller.getClassLoader();if ((ccl != null) && (ccl != cl) &&((cl == null) || !isAncestor(cl, ccl))) {sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);}} catch (PrivilegedActionException pae) {throw new RuntimeException(pae.getException());} catch (Exception ex) {throw new RuntimeException(ex);}if (field.getType() != long.class)throw new IllegalArgumentException("Must be long type");if (!Modifier.isVolatile(modifiers))throw new IllegalArgumentException("Must be volatile type");// Access to protected field members is restricted to receivers only// of the accessing class, or one of its subclasses, and the// accessing class must in turn be a subclass (or package sibling)// of the protected member's defining class.// If the updater refers to a protected field of a declaring class// outside the current package, the receiver argument will be// narrowed to the type of the accessing class.this.cclass = (Modifier.isProtected(modifiers) &&tclass.isAssignableFrom(caller) &&!isSamePackage(tclass, caller))? caller : tclass;this.tclass = tclass;this.offset = U.objectFieldOffset(field);}public final boolean compareAndSet(T obj, long expect, long update) {accessCheck(obj);return U.compareAndSwapLong(obj, offset, expect, update);}}private static final class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {LockedUpdater(final Class<T> tclass, final String fieldName,final Class<?> caller) {Field field = null;int modifiers = 0;try {field = AccessController.doPrivileged(new PrivilegedExceptionAction<Field>() {public Field run() throws NoSuchFieldException {return tclass.getDeclaredField(fieldName);}});modifiers = field.getModifiers();sun.reflect.misc.ReflectUtil.ensureMemberAccess(caller, tclass, null, modifiers);ClassLoader cl = tclass.getClassLoader();ClassLoader ccl = caller.getClassLoader();if ((ccl != null) && (ccl != cl) &&((cl == null) || !isAncestor(cl, ccl))) {sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);}} catch (PrivilegedActionException pae) {throw new RuntimeException(pae.getException());} catch (Exception ex) {throw new RuntimeException(ex);}if (field.getType() != long.class)throw new IllegalArgumentException("Must be long type");if (!Modifier.isVolatile(modifiers))throw new IllegalArgumentException("Must be volatile type");// Access to protected field members is restricted to receivers only// of the accessing class, or one of its subclasses, and the// accessing class must in turn be a subclass (or package sibling)// of the protected member's defining class.// If the updater refers to a protected field of a declaring class// outside the current package, the receiver argument will be// narrowed to the type of the accessing class.this.cclass = (Modifier.isProtected(modifiers) &&tclass.isAssignableFrom(caller) &&!isSamePackage(tclass, caller))? caller : tclass;this.tclass = tclass;this.offset = U.objectFieldOffset(field);}public final boolean compareAndSet(T obj, long expect, long update) {accessCheck(obj);synchronized (this) {long v = U.getLong(obj, offset);if (v != expect)return false;U.putLong(obj, offset, update);return true;}}}}
AtomicReferenceFieldUpdater
public abstract class AtomicReferenceFieldUpdater<T,V> {@CallerSensitivepublic static <U,W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass,Class<W> vclass,String fieldName) {return new AtomicReferenceFieldUpdaterImpl<U,W>(tclass, vclass, fieldName, Reflection.getCallerClass());}public abstract boolean compareAndSet(T obj, V expect, V update);private static final class AtomicReferenceFieldUpdaterImpl<T,V>extends AtomicReferenceFieldUpdater<T,V> {private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();private final long offset;private final Class<?> cclass;private final Class<T> tclass;private final Class<V> vclass;AtomicReferenceFieldUpdaterImpl(final Class<T> tclass,final Class<V> vclass,final String fieldName,final Class<?> caller) {final Field field;final Class<?> fieldClass;final int modifiers;try {field = AccessController.doPrivileged(new PrivilegedExceptionAction<Field>() {public Field run() throws NoSuchFieldException {return tclass.getDeclaredField(fieldName);}});modifiers = field.getModifiers();sun.reflect.misc.ReflectUtil.ensureMemberAccess(caller, tclass, null, modifiers);ClassLoader cl = tclass.getClassLoader();ClassLoader ccl = caller.getClassLoader();if ((ccl != null) && (ccl != cl) &&((cl == null) || !isAncestor(cl, ccl))) {sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);}fieldClass = field.getType();} catch (PrivilegedActionException pae) {throw new RuntimeException(pae.getException());} catch (Exception ex) {throw new RuntimeException(ex);}if (vclass != fieldClass)throw new ClassCastException();if (vclass.isPrimitive())throw new IllegalArgumentException("Must be reference type");if (!Modifier.isVolatile(modifiers))throw new IllegalArgumentException("Must be volatile type");// Access to protected field members is restricted to receivers only// of the accessing class, or one of its subclasses, and the// accessing class must in turn be a subclass (or package sibling)// of the protected member's defining class.// If the updater refers to a protected field of a declaring class// outside the current package, the receiver argument will be// narrowed to the type of the accessing class.this.cclass = (Modifier.isProtected(modifiers) &&tclass.isAssignableFrom(caller) &&!isSamePackage(tclass, caller))? caller : tclass;this.tclass = tclass;this.vclass = vclass;this.offset = U.objectFieldOffset(field);}public final boolean compareAndSet(T obj, V expect, V update) {accessCheck(obj);valueCheck(update);return U.compareAndSwapObject(obj, offset, expect, update);}}}

在单个cas + 自旋的操作下会有性能问题,所以采用分治的思想 将一个变量的累加分散到一个cells 数组中进行,随后用过sum 方法进行聚合,返回用户

原子累加器(Atomic 类源码浅析二 )

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

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

相关文章

1-Tornado的介绍

1 tornado的介绍 **Tornado**是一个用Python编写的可扩展的、无阻塞的**Web应用程序框架**和**Web服务器**。 它是由FriendFeed开发使用的&#xff1b;该公司于2009年被Facebook收购&#xff0c;而Tornado很快就开源了龙卷风以其高性能着称。它的设计允许处理大量并发连接&…

Spark常见算子汇总

创建RDD 在Spark中创建RDD的方式分为三种: 从外部存储创建RDD从集合中创建RDD从其他RDD创建 textfile 调用SparkContext.textFile()方法&#xff0c;从外部存储中读取数据来创建 RDD parallelize 调用SparkContext 的 parallelize()方法&#xff0c;将一个存在的集合&…

这些Java并发容器,你都了解吗?

文章目录 前言并发容器1.ConcurrentHashMap 并发版 HashMap示例 2.CopyOnWriteArrayList 并发版 ArrayList示例 3.CopyOnWriteArraySet 并发 Set示例 4.ConcurrentLinkedQueue 并发队列 (基于链表)示例 5.ConcurrentLinkedDeque 并发队列 (基于双向链表)示例 6.ConcurrentSkipL…

Vue学习计划-Vue2--Vue核心(五)条件、列表渲染、表单数据

1. 条件渲染 v-if v-if“表达式”v-else-if “表达式”v-else “表达式” 适用于&#xff1a;切换频率较低的场景 特点&#xff1a;不显示dom元素&#xff0c;直接被删除 注意&#xff1a;v-if和v-else-if、v-else一起使用&#xff0c;但要求结构不能被打断 v-if和template一…

Android笔记(十七):PendingIntent简介

PendingIntent翻译成中文为“待定意图”&#xff0c;这个翻译很好地表示了它的涵义。PendingIntent描述了封装Intent意图以及该意图要执行的目标操作。PendingIntent封装Intent的目标行为的执行是必须满足一定条件&#xff0c;只有条件满足&#xff0c;才会触发意图的目标操作。…

Kotlin 中的 also 和 run:选择正确的作用域函数

在 Kotlin 中&#xff0c;also 和 run 是两个十分有用的作用域函数。 虽然它们在功能上相似&#xff0c;但各自有独特的用途和适用场景。 一、分析&#xff1a; also&#xff1a;在对象的上下文中执行给定的代码块&#xff0c;并返回对象本身。它的参数是一个接收对象并返回…

分布式分布式事务分布式锁分布式ID

目录 分布式分布式系统设计理念目标设计思路中心化去中心化 基本概念分布式与集群NginxRPC消息中间件&#xff08;MQ&#xff09;NoSQL&#xff08;非关系型数据库&#xff09; 分布式事务1 事务2 本地事务3 分布式事务4 本地事务VS分布式事务5 分布式事务场景6 CAP原理7 CAP组…

ChatGPT发展历程

ChatGPT是一个在2020年成立的在线聊天平台&#xff0c;它的发展历程如下&#xff1a; 初期阶段&#xff1a;2020年&#xff0c;在全球疫情爆发的情况下&#xff0c;ChatGPT创始人开始思考如何为人们提供一个快捷、安全、便利的在线聊天平台。他们选择使用GPT&#xff08;生成对…

(2/2)敏捷实践指南 Agile Practice Guide ([美] Project Management institute 著)

附录 A1 - 《PMBOK指南》映射 表A1显示了第六版《PMBOK指南》中定义的项目管理过程组与知识领域之间的对应关系 本附录说明了如何利用混合和敏捷方法处理《PMBOK指南》知识领域&#xff08;请参见表A1-2&#xff09;中所述的属性&#xff0c;其中涵盖了相同和不同的属性&…

conda 安装教程分享

大家好&#xff0c;我是微赚淘客系统的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我将向大家介绍如何使用conda进行安装。 首先&#xff0c;让我们来了解一下conda。conda是Anaconda发行版的一部分&#xff0c;它是一个开源的包管理系…

为什么那些删库跑路的人都极其下流

为什么那些删库跑路的人都极其下流&#xff1f;因为真的下流。注意&#xff0c;我不是针对跑路者的人品&#xff0c;遇到不公正待遇不敢反抗本身就比下流还下流&#xff0c;我说的是这种对抗方式太多低等。 干不好是能力问题&#xff0c;你不干是态度问题。记住我的话&#xf…

golang版aes-cbc-pkcs7加密解密base64hex字符串输入输出

最近项目中golang项目中使用aes加解密&#xff0c;做个记录方便以后使用 aes-cbc-pkcs7加密解密base64输入输出 type AesBase64 struct {key []byte // 允许16,24,32字节长度iv []byte // 只允许16字节长度 }func NewAesBase64(key []byte, iv []byte) *AesBase64 {return &…

C#网络应用程序(Web页面浏览器、局域网聊天程序)

目录 一、创建Web页面浏览器 1.示例源码 2.生成效果 二、局域网聊天程序 1.类 2.服务器端 3.客户端 一、创建Web页面浏览器 TextBox 控件用来输入要浏览的网页地址&#xff0c;Button控件用来执行浏览网页操作&#xff0c; WebBrowser控件用来显示要浏览的网页。这个控…

Matlab 曲线动态绘制

axes(handles.axes1); % 选定所画坐标轴 figure也可 h1 animatedline; h1.Color b; h1.LineWidth 2; h1.LineStyle -; % 线属性设置 for i 1 : length(x)addpoints(h1,x(i),y(i)); % x/y为待绘制曲线数据drawnow;pause(0.01); % 画点间停顿 end 示例&#xff1a; figure…

exynos4412—中断处理

一、什么是中断 一种硬件上的通知机制&#xff0c;用来通知CPU发生了某种需要立即处理的事件 分为&#xff1a; 内部中断 CPU执行程序的过程中&#xff0c;发生的一些硬件出错、运算出错事件&#xff08;如分母为0、溢出等等&#xff09;&#xff0c;不可屏蔽外部中断 外设发…

scitb包1.6版本发布,一个为制作专业统计表格而生的R包

目前&#xff0c;本人写的scitb包1.6版本已经正式在R语言官方CRAN上线&#xff0c;scitb包是一个为生成专业化统计表格而生的R包。 可以使用以下代码安装 install.packages("scitb")安装过旧版本的从新安装一次就可以升级了,根据粉丝的建议&#xff0c;增加了Overal…

RocketMQ-RocketMQ集群实践(搭建)

搭建RocketMQ可视化管理服务 下载可视化客户端源码下载 | RocketMQ 这里只提供了源码&#xff0c;并没有提供直接运行的jar包。将源码下载下来后&#xff0c;需要解压并进入对应的目录&#xff0c;使用maven进行编译。(需要提前安装maven客户端) mvn clean package -Dmaven.t…

手动部署1个Cloud Run service

什么是Cloud Run 来自chatgpt&#xff1a; Google Cloud Run 是一项全托管的服务器托管平台&#xff0c;它允许您在容器化的环境中运行无服务器应用程序。Cloud Run 提供了一种简单而灵活的方式来构建、部署和扩展应用程序&#xff0c;无需管理底层基础设施。 以下是 Cloud …

sql常用语法练习

表名word namecontinentareapopulationgdpAfghanistanAsia6522302550010020343000000AlbaniaEurope28748283174112960000000AlgeriaAfrica238174137100000188681000000AndorraEurope468781153712000000AngolaAfrica124670020609294100990000000.... 基础练习 基础查询 1、阅…

RocketMq实战(待完善)

目录 生产者 发送消息固定步骤 发送模式 1. 单向发送 2. 同步发送 3. 异步发送 生产消息完整代码 消费者 消费消息固定步骤 简单消费代码示例 消息模型 广播消息 顺序消息 延迟消息 批量消息 事务消息 生产者 发送消息固定步骤 1.创建消息生产者producer&#…