Java Lock LockSupport 源码
前言
相关系列
- 《Java & Lock & 目录》(持续更新)
- 《Java & Lock & LockSupport & 源码》(学习过程/多有漏误/仅作参考/不再更新)
- 《Java & Lock & LockSupport & 总结》(学习总结/最新最准/持续更新)
- 《Java & Lock & LockSupport & 问题》(学习解答/持续更新)
源码
/** ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.*********************//******* Written by Doug Lea with assistance from members of JCP JSR-166* Expert Group and released to the public domain, as explained at* http://creativecommons.org/publicdomain/zero/1.0/*/package juc.locks;import juc.Semaphore;
import sun.misc.Unsafe;import java.util.concurrent.ThreadLocalRandom;/*** Basic thread blocking primitives for creating locks and other synchronization classes.* 用于创建锁和其它同步类的基本线程阻塞原语。* <p>* This class associates, with each thread that uses it, a permit (in the sense of the* {@link Semaphore Semaphore} class). A call to {@code park} will return immediately if the permit is available,* consuming it in the process; otherwise it <em>may</em> block. A call to {@code unpark} makes the permit available,* if it was not already available. (Unlike with Semaphores though, permits do not accumulate. There is at most one.)* 该类与每个使用它的线程关联一个许可(从信号量类的角度上看)。如果许可可用则调用一次park()方法将立即返回,并* 在过程中消费它;否则它将可能阻塞。如果许可不可用,则调用一次unpark()方法可使得其可用。(但是不像信号量,许* 可无法累积。最多只能有一个。)* <p>* Methods {@code park} and {@code unpark} provide efficient means of blocking and unblocking threads that do not* encounter the problems that cause the deprecated methods {@code Thread.suspend} and {@code Thread.resume} to* beunusable for such purposes: Races between one thread invoking {@code park} and another thread trying to* {@code unpark} it will preserve liveness, due to the permit. Additionally, {@code park} will return if the caller's* threadwas interrupted, and timeout versions are supported. The {@code park} method may also return at any other* time, for "no reason", so in general must be invoked within a loop that rechecks conditions upon return. In this sense* {@code park}serves as an optimization of a "busy wait" that does not waste as much time spinning, but must be* paired with an {@code unpark} to be effective.* 方法park和unpark提供了阻塞和解除阻塞线程的有效方法,这些方法不会遇到导致已弃用方法suspend和resume对于如此* 目的无用的问题:在线程调用park方法与其它线程尝试unpark它之间竞争将由于许可而保持活性。此外,如果调用者的线* 程已被中断,以及支持超时版本则park将返回。park方法也可能在任意其它时间无理由的返回,所以通常必须在返回后检* 查条件的循环中被调用。从这个角度上看park方法作为忙等待的优化手段不会浪费太多自旋时间,但必须与一个unpark方* 法成对使用以令之有效。* <p>* The three forms of {@code park} each also support a {@code blocker} object parameter. This object is recorded while* the thread is blocked to permit monitoring and diagnostic tools to identify the reasons that threads are blocked. (Such* tools may access blockers using method {@link #getBlocker(Thread)}.) The use of these forms rather than the original* forms without this parameter is strongly encouraged. The normal argument to supply as a {@code blocker} within a* lock implementation is {@code this}.* park方法的三种格式每个都支持一个阻塞者对象参数。该对象在线程在线程阻塞期间被记录,以允许监视器和诊断工具识* 别线程阻塞的原因。(该工具可能访问使用getBlocker(Thread)方法访问阻塞者)。强烈鼓励使用这些格式而不是原本没有* 参数的原始格式。该常规参数用于在一个锁实现中供应一个阻塞者。* <p>* These methods are designed to be used as tools for creating higher-level synchronization utilities, and are not in* themselves useful for most concurrency control applications. The {@code park} method is designed for use only in* constructions of the form:* 这些方法被设计用于作为创建更高等级的同步程序的工具,并且它们本身对于大多数并发控制应用程序并没有用(意思是* 不会在API中使用相应的方法保证线程安全,而是使用基于它们创建的线程安全工具保证线程安全)。park方法被设计只在* 以下格式中构造:* <pre> {@code* while (!canProceed()) { ... LockSupport.park(this); }}</pre>* <p>* where neither {@code canProceed} nor any other actions prior to the call to {@code park} entail locking or blocking.* Because only one permit is associated with each thread, any intermediary uses of {@code park} could interfere with* its intended effects.* 其中即不是canProceed方法也不是任意其它优先于park方法的活动都需要加锁或阻塞(意思是循环中位于park方法之后的* 代码都必须是线程安全的...妈的什么鬼英语)。因为线程只关联一个许可,因此任意park方法的中间调用都会干涉它的预* 期效果(简而言之就是要要避免外部干扰)。** <p>* <b>Sample Usage.</b> Here is a sketch of a first-in-first-out non-reentrant lock class:* 简单用法。这是一个先入先出非重入锁类的草图:* <pre> {@code* class FIFOMutex {* // ---- 原子布尔,作为锁使用。* private final AtomicBoolean locked = new AtomicBoolean(false);* // ---- 等待者队列。* private final Queue<Thread> waiters = new ConcurrentLinkedQueue<Thread>();** // ---- 加锁。* public void lock() {* // ---- 经线程加入等待者集中。* boolean wasInterrupted = false;* Thread current = Thread.currentThread();* waiters.add(current);** // Block while not first in queue or cannot acquire lock* // 在非队列首个线程或无法获取锁的情况下阻塞** while (waiters.peek() != current || !locked.compareAndSet(false, true)) {* LockSupport.park(this);* if (Thread.interrupted())* // ignore interrupts while waiting* // 忽略在等待期间的中断(即该方法在设计上是不允许被中断的)* wasInterrupted = true;* }* // ---- 退出循环后,将当前线程从等待者集中移除。* waiters.remove();* // reassert interrupt status on exit* // 在退出时重设中断状态。* if (wasInterrupted)* current.interrupt();* }** public void unlock() {* locked.set(false);* // ---- 唤醒等待者集中的首个线程。* LockSupport.unpark(waiters.peek());* }* }}</pre>*/
public class LockSupport {/*** @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------* ----* @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------* 初始化锁支持者* @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------* ----*/private LockSupport() {// Cannot be instantiated.// 无法(外部)实例化}/*** @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------* 设置阻塞者* @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------* 为指定线程设置指定阻塞者* @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------* ---- 方法直接通过CAS操作完成。*/private static void setBlocker(Thread t, Object arg) {// Even though volatile, hotspot doesn't need a write barrier here.// 虽然易变,但热点在这里不需要一个写屏障。UNSAFE.putObject(t, parkBlockerOffset, arg);}/*** Makes available the permit for the given thread, if it was not already available. If the thread was blocked on* {@code park} then it will unblock. Otherwise, its next call to {@code park} is guaranteed not to block. This* operation is not guaranteed to have any effect at all if the given thread has not been started.* 如果指定线程尚未可用,则令其许可可用。如果线程它因为park方法而阻塞则它将解除阻塞。否则,它的下次park方* 法调用将不保证阻塞。如果指定线程尚未启动则该操作无法保证在任意情况下都有效果。** @param thread the thread to unpark, or {@code null}, in which case this operation has no effect* 用于释放的线程,或者为null,在该情况下该操作没有效果* @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------* 解除停放* @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------* 为指定线程分配一个许可,如果指定线程因为许可负债(-1)而处于等待状态,则将因为负债被清零而恢复运行;如果* 指定线程因为许可平衡(0)而处于运行状态,则将因为许可结余(1)而不会在下一次许可消耗中进入等待状态。如果* 执行线程尚未启动则上述所有情况都不保证一定会发生。* @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------* ---- 方法直接通过CAS机制实现。*/public static void unpark(Thread thread) {if (thread != null)UNSAFE.unpark(thread);}/*** Disables the current thread for thread scheduling purposes unless the permit is available.* 出于线程调度目的令当前线程无效,除非许可可用。* <p>* If the permit is available then it is consumed and the call returns immediately; otherwise the current thread becomes* disabled for thread scheduling purposes and lies dormant until one of three things happens:* 如果许可可用则消费许可并立即返回;否则当前线程处于线程调度目的将变得无效,并且休眠至以下三种情况发生:* <ul>* <li>Some other thread invokes {@link #unpark unpark} with the current thread as the target; or* 某些其它线程将当前线程作为目标调用unpark方法;或者* <li>Some other thread {@linkplain Thread#interrupt interrupts} the current thread; or* 某些其它线程中断当前线程;或者* <li>The call spuriously (that is, for no reason) returns. </ul>* 该调用虚假地(无理由地)返回。* <p>* This method does <em>not</em> report which of these caused the method to return. Callers should re-check the* conditions which caused the thread to park in the first place. Callers may also determine, for example, the* interrupt status of the thread upon return.* 该方法不会记录什么导致方法返回。调用者首先应该重检查导致线程停泊的条件(是否满足)。调用者可能还要确定,* 例如,线程返回后的中断状态。** @param blocker the synchronization object responsible for this thread parking* 该同步对象负责当前线程的停泊* @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------* 停泊* @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------* 消耗指定线程的一个许可,消耗后如果指定线程许可负债(-1)则进入无限等待状态;直至因为信号、中断及虚假的原* 因而唤醒;否则直接返回。* @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------* ---- 方法首先会为指定线程设置阻塞者,随后令之进入等待状态,如果被唤醒或进入等待状态失败则将阻塞者清除并返* 回。阻塞者的作用是令唤醒当前线程可以判断是否满足条件,功能是自定义的。* @since 1.6*/public static void park(Object blocker) {// ---- 方法首先会为指定线程设置阻塞者,随后令之进入等待状态,如果被唤醒或进入等待状态失败则将阻塞者清除// 并返回。阻塞者的作用是令唤醒当前线程可以判断是否满足条件,功能是自定义的。Thread t = Thread.currentThread();setBlocker(t, blocker);UNSAFE.park(false, 0L);setBlocker(t, null);}/*** Disables the current thread for thread scheduling purposes, for up to the specified waiting time, unless the permit* is available.* 出于调度线程的目的令当前线程无效,直至指定等待时间,除非许可可用。* <p>* If the permit is available then it is consumed and the call returns immediately; otherwise the current thread becomes* disabled for thread scheduling purposes and lies dormant until one of four things happens:* 如果许可可用则消费许可并立即返回;否则当前线程处于线程调度目的将变得无效,并且休眠至以下四种情况发生:* <ul>* <li>Some other thread invokes {@link #unpark unpark} with the current thread as the target; or* 某些其它线程将当前线程作为目标调用unpark方法;或者* <li>Some other thread {@linkplain Thread#interrupt interrupts} the current thread; or* 某些其它线程中断当前线程;或者* <li>The specified waiting time elapses; or* 指定等待时间消逝;或者* <li>The call spuriously (that is, for no reason) returns. </ul>* 该调用虚假地(无理由地)返回。* </ul>** <p>* This method does <em>not</em> report which of these caused the method to return. Callers should re-check the* conditions which caused the thread to park in the first place. Callers may also determine, for example, the* interrupt status of the thread, or the elapsed time upon return.* 该方法不会记录什么导致方法返回。调用者首先应该重检查导致线程停泊的条件(是否满足)。调用者可能还要确定,* 例如,线程返回后的中断状态,或过期时间。** @param blocker the synchronization object responsible for this thread parking* 该同步对象负责当前线程的停泊* @param nanos the maximum number of nanoseconds to wait* 等待的最大纳秒时间* @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------* 停泊纳秒* @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------* 消耗指定线程的一个许可,消耗后如果指定线程许可负债(-1)则进入有限等待状态;直至因为信号、中断、超时及虚* 假的原因而唤醒;否则直接返回。* @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------* ---- 方法首先会判断指定等待时间是否合法,合法则为指定线程设置阻塞者,随后令之进入等待状态,如果被唤醒或进* 入等待状态失败则将阻塞者清除并返回。* @since 1.6*/public static void parkNanos(Object blocker, long nanos) {if (nanos > 0) {Thread t = Thread.currentThread();setBlocker(t, blocker);UNSAFE.park(false, nanos);setBlocker(t, null);}}/*** Disables the current thread for thread scheduling purposes, until the specified deadline, unless the permit is available.* 出于调度线程的目的令当前线程无效,直至指定死亡线,除非许可可用。* <p>* If the permit is available then it is consumed and the call returns immediately; otherwise the current thread becomes* disabled for thread scheduling purposes and lies dormant until one of four things happens:* 如果许可可用则消费许可并立即返回;否则当前线程处于线程调度目的将变得无效,并且休眠至以下四种情况发生:* <ul>* <li>Some other thread invokes {@link #unpark unpark} with the current thread as the target; or* 某些其它线程将当前线程作为目标调用unpark方法;或者* <li>Some other thread {@linkplain Thread#interrupt interrupts} the current thread; or* 某些其它线程中断当前线程;或者* <li>The specified waiting time elapses; or* 指定等待时间消逝;或者* <li>The call spuriously (that is, for no reason) returns. </ul>* 该调用虚假地(无理由地)返回。* </ul>* <p>* This method does <em>not</em> report which of these caused the method to return. Callers should re-check the* conditions which caused the thread to park in the first place. Callers may also determine, for example, the* interrupt status of the thread, or the current time upon return.* 该方法不会记录什么导致方法返回。调用者首先应该重检查导致线程停泊的条件(是否满足)。调用者可能还要确定,* 例如,线程返回后的中断状态,或过期时间。** @param blocker the synchronization object responsible for this thread parking* 该同步对象负责当前线程的停泊* @param deadline the absolute time, in milliseconds from the Epoch, to wait until* 从纪元到等待的绝对时间,以毫秒为单位* @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------* 停泊直至* @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------* 消耗指定线程的一个许可,消耗后如果指定线程许可负债(-1)则进入有限等待状态;直至因为信号、中断、超时及虚* 假的原因而唤醒;否则直接返回。* @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------* ---- 方法首先会为指定线程设置阻塞者,随后令之进入等待状态,如果被唤醒或进入等待状态失败则将阻塞者清除并返* 回。* @since 1.6*/public static void parkUntil(Object blocker, long deadline) {Thread t = Thread.currentThread();setBlocker(t, blocker);UNSAFE.park(true, deadline);setBlocker(t, null);}/*** Returns the blocker object supplied to the most recent invocation of a park method that has not yet unblocked, or* null if not blocked. The value returned is just a momentary snapshot -- the thread may have since unblocked or* blocked on a different blocker object.* 返回由最近一次还未解除阻塞的park方法调用提供的阻塞者对象,或者如果未阻塞则为null。返回的值只是一个短暂的* 快照-- 该线程可能已解除阻塞或在另一个阻塞对象中阻塞。** @param t the thread 线程* @return the blocker 阻塞者* @throws NullPointerException if argument is null* 空指针异常:如果参数为null* @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------* 获取阻塞者* @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------* 获取当前线程的阻塞者。* @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------* ----* @since 1.6*/public static Object getBlocker(Thread t) {if (t == null)throw new NullPointerException();return UNSAFE.getObjectVolatile(t, parkBlockerOffset);}/*** Disables the current thread for thread scheduling purposes unless the permit is available.* 出于线程调度目的令当前线程无效,除非许可可用。* <p>* If the permit is available then it is consumed and the call returns immediately; otherwise the current thread becomes* disabled for thread scheduling purposes and lies dormant until one of three things happens:* 如果许可可用则消费许可并立即返回;否则当前线程处于线程调度目的将变得无效,并且休眠至以下三种情况发生:* <ul>* <li>Some other thread invokes {@link #unpark unpark} with the current thread as the target; or* 某些其它线程将当前线程作为目标调用unpark方法;或者* <li>Some other thread {@linkplain Thread#interrupt interrupts} the current thread; or* 某些其它线程中断当前线程;或者* <li>The call spuriously (that is, for no reason) returns. </ul>* 该调用虚假地(无理由地)返回。* </ul>** <p>* This method does <em>not</em> report which of these caused the method to return. Callers should re-check the* conditions which caused the thread to park in the first place. Callers may also determine, for example, the* interrupt status of the thread upon return.* 该方法不会记录什么导致方法返回。调用者首先应该重检查导致线程停泊的条件(是否满足)。调用者可能还要确定,* 例如,线程返回后的中断状态。** @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------* 停泊* @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------* 消耗指定线程的一个许可,消耗后如果指定线程许可负债(-1)则进入无限等待状态;直至因为信号、中断及虚假的原* 因而唤醒;否则直接返回。* @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------* ----*/public static void park() {UNSAFE.park(false, 0L);}/*** Disables the current thread for thread scheduling purposes, for up to the specified waiting time, unless the permit* is available.* 出于调度线程的目的令当前线程无效,直至指定等待时间,除非许可可用。** <p>* If the permit is available then it is consumed and the call returns immediately; otherwise the current thread becomes* disabled for thread scheduling purposes and lies dormant until one of four things happens:* 如果许可可用则消费许可并立即返回;否则当前线程处于线程调度目的将变得无效,并且休眠至以下四种情况发生:* <ul>* <li>Some other thread invokes {@link #unpark unpark} with the current thread as the target; or* 某些其它线程将当前线程作为目标调用unpark方法;或者* <li>Some other thread {@linkplain Thread#interrupt interrupts} the current thread; or* 某些其它线程中断当前线程;或者* <li>The specified waiting time elapses; or* 指定等待时间消逝;或者* <li>The call spuriously (that is, for no reason) returns. </ul>* 该调用虚假地(无理由地)返回。* </ul>** <p>* This method does <em>not</em> report which of these caused the method to return. Callers should re-check the* conditions which caused the thread to park in the first place. Callers may also determine, for example, the* interrupt status of the thread, or the elapsed time upon return.* 该方法不会记录什么导致方法返回。调用者首先应该重检查导致线程停泊的条件(是否满足)。调用者可能还要确定,* 例如,线程返回后的中断状态,或过期时间。** @param nanos the maximum number of nanoseconds to wait* 等待的最大纳秒时间* @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------* 停泊纳秒* @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------* 消耗指定线程的一个许可,消耗后如果指定线程许可负债(-1)则进入有限等待状态;直至因为信号、中断、超时及虚* 假的原因而唤醒;否则直接返回。* @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------* ----*/public static void parkNanos(long nanos) {if (nanos > 0)UNSAFE.park(false, nanos);}/*** Disables the current thread for thread scheduling purposes, until the specified deadline, unless the permit is available.* 出于调度线程的目的令当前线程无效,直至指定死亡线,除非许可可用。* <p>* If the permit is available then it is consumed and the call returns immediately; otherwise the current thread becomes* disabled for thread scheduling purposes and lies dormant until one of four things happens:* 如果许可可用则消费许可并立即返回;否则当前线程处于线程调度目的将变得无效,并且休眠至以下四种情况发生:* <ul>* <li>Some other thread invokes {@link #unpark unpark} with the current thread as the target; or* 某些其它线程将当前线程作为目标调用unpark方法;或者* <li>Some other thread {@linkplain Thread#interrupt interrupts} the current thread; or* 某些其它线程中断当前线程;或者* <li>The specified waiting time elapses; or* 指定等待时间消逝;或者* <li>The call spuriously (that is, for no reason) returns. </ul>* 该调用虚假地(无理由地)返回。* </ul>* <p>* This method does <em>not</em> report which of these caused the method to return. Callers should re-check the* conditions which caused the thread to park in the first place. Callers may also determine, for example, the* interrupt status of the thread, or the current time upon return.* 该方法不会记录什么导致方法返回。调用者首先应该重检查导致线程停泊的条件(是否满足)。调用者可能还要确定,* 例如,线程返回后的中断状态,或过期时间。** @param deadline the absolute time, in milliseconds from the Epoch, to wait until* 从纪元到等待的绝对时间,以毫秒为单位* @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------* 停泊直至* @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------* 消耗指定线程的一个许可,消耗后如果指定线程许可负债(-1)则进入有限等待状态;直至因为信号、中断、超时及虚* 假的原因而唤醒;否则直接返回。* @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------* ---- 方法首先会为指定线程设置阻塞者,随后令之进入等待状态,如果被唤醒或进入等待状态失败则将阻塞者清除并返* 回。*/public static void parkUntil(long deadline) {UNSAFE.park(true, deadline);}/*** Returns the pseudo-randomly initialized or updated secondary seed. Copied from ThreadLocalRandom due to package* access restrictions.* 虚假随机地返回初始化的或更新的次要个种子。由于包访问限制从ThreadLocalRandom中赋值。** @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------* 下个次要种子* @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------* 基于当前线程的次要种子生成新的次要种子并保存/返回。* @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------* ---- 方法首先会从当前线程中获取次要种子并判断是否为0,为0表示为初始值,为之随机分配一个值。但为了防止随机* 的数值为0需要在该情况下手动将之赋值为1;如果不为0则说明次要种子已经被更新过,基于其进行位运算已生成新的* 次要种子。* ---- 新的次要种子生成后将之重新保存至当前线程中并返回。*/static final int nextSecondarySeed() {int r;Thread t = Thread.currentThread();if ((r = UNSAFE.getInt(t, SECONDARY)) != 0) {// ---- 从线程中获取次要种子,如果不为0,说明已经经历过更新,直接进行位操作。r ^= r << 13; // xorshiftr ^= r >>> 17;r ^= r << 5;} else if ((r = ThreadLocalRandom.current().nextInt()) == 0)// avoid zero// 避免0// ---- 如果次要种子为0,说明为初始值,尚未经历过更新,因此为之分配一个随机数。但是为了防止其再次为0需// 要在其位0是手动赋值为1。r = 1;// ---- 新的次要种子被分配后,重新保存。UNSAFE.putInt(t, SECONDARY, r);return r;}// Hotspot implementation via intrinsics APIprivate static final Unsafe UNSAFE;private static final long parkBlockerOffset;private static final long SEED;private static final long PROBE;private static final long SECONDARY;static {try {UNSAFE = Unsafe.getUnsafe();Class<?> tk = Thread.class;parkBlockerOffset = UNSAFE.objectFieldOffset(tk.getDeclaredField("parkBlocker"));SEED = UNSAFE.objectFieldOffset(tk.getDeclaredField("threadLocalRandomSeed"));PROBE = UNSAFE.objectFieldOffset(tk.getDeclaredField("threadLocalRandomProbe"));SECONDARY = UNSAFE.objectFieldOffset(tk.getDeclaredField("threadLocalRandomSecondarySeed"));} catch (Exception ex) {throw new Error(ex);}}}
相关文章:
Java Lock LockSupport 源码
前言 相关系列 《Java & Lock & 目录》(持续更新)《Java & Lock & LockSupport & 源码》(学习过程/多有漏误/仅作参考/不再更新)《Java & Lock & LockSupport & 总结》(学习总结/最新…...
Elasticsearch基础操作入门
阅前准备知识 学习 Elasticsearch (简称 ES) 的查询方式,建议从以下几个步骤入手: 理解 Elasticsearch 的基础概念 首先要了解 Elasticsearch 的核心概念,例如: Index(索引):相当于数据库中…...
跨域问题解决办法
跨域问题在Web开发中是一个常见的问题,特别是在前后端分离的开发模式下。以下是一些解决跨域问题的办法: 一、后端配置CORS(跨来源资源共享) CORS是一种机制,它使用额外的HTTP头来告诉浏览器一个网页的当前来源&…...
【数据结构与算法】力扣 23. 合并 K 个升序链表
题干描述 23. 合并 K 个升序链表 给你一个链表数组,每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表中,返回合并后的链表。 示例 1: 输入: lists [[1,4,5],[1,3,4],[2,6]] 输出: [1,1,2,3,4,4,5,6]…...

Java Lock CountDownLatch 总结
前言 相关系列 《Java & Lock & 目录》(持续更新)《Java & Lock & CountDownLatch & 源码》(学习过程/多有漏误/仅作参考/不再更新)《Java & Lock & CountDownLatch & 总结》(学习总…...

vue+spreadjs开发
创建vue3项目 pnpm create vite --registryhttp://registry.npm.taobao.org安装spreadjs包 pnpm install "grapecity-software/spread-sheets17.1.7" "grapecity-software/spread-sheets-resources-zh17.1.7" "grapecity-software/spread-sheets-vu…...
针对初学者的PyTorch项目推荐
文章目录 1. MNIST手写数字识别2. CIFAR-10图像分类3. 图像风格迁移4. 文本生成(使用RNN)5. 简单的问答系统6. 简单的生成对抗网络(GAN)7. 简单的推荐系统 对于初学者来说,选择一些简单且具有教育意义的项目来实践PyTo…...
Helm Chart文件介绍
介绍(这个还没有完善 ,目前在找工作呢) Helm是Kubernetes的包管理器,类似于Ubuntu中的apt、CentOS中的yum或Python中的pip,可以快速查找、下载和安装软件包。Helm主要由客户端组件helm和服务端组件Tiller组成…...

1Panel 是新一代的 Linux 服务器运维管理面板
1Panel 是一款新一代的 Linux 服务器运维管理面板,旨在通过现代化的 Web 界面帮助用户轻松管理 Linux 服务器。它集成了主机监控、文件管理、数据库管理、容器管理等功能,并且支持多语言和国际化,包括英语、中文(繁体)和日语。以下是 1Panel …...

Qml-ShaderEffect的使用
Qml-ShaderEffect的使用 ShaderEffect的概述 ShaderEffect使用自定义的顶点和片段着色器用于渲染一个矩形。用于在qml场景中添加阴影、模糊、着色和页面卷曲等效果。 Qt5和Qt6中ShaderEffect有一定区别,在Qt6中由于支持不同的渲染API,ShaderEffect是用…...
鸿蒙next之axios二次封装并携带cookie
由于官方提供的ohos.net.http模块,直接使用不是很灵活,就引入了第三方ohos/axios库。 以下是引入axios并进行二次封装的步骤: 1、DevEco Studio打开终端输入命令安装插件 ohpm install ohos/axios 2、新建RequestUtil.ets import { JSON, …...

WordPress中最值得推荐的AI插件:专家级指南
WordPress平台上,人工智能(AI)技术不断发展,为用户提供了丰富的工具和功能。对于有经验的用户,这些工具不仅能提升网站性能和用户体验,还能在安全和互动方面提供更多支持。在这篇文章中,我将为大…...
HTTP介绍及请求过程
HTTP(HyperText Transfer Protocol),即超文本传输协议,是一种用于分布式、协作式和超媒体信息系统的应用层协议。以下是关于 HTTP 的详细介绍: 一、基本概念 定义与作用: HTTP 是互联网上应用最为广泛的一种网络协议,它定义了客户端和服务器之间请求和响应的标准方式。…...

WebGL进阶(五)-可视域
理论基础: 顶点着色器 Vertex Shader 主要是负责处理顶点位置、顶点颜色、顶点向量等顶点的数据;处理一些顶点的变换:例如在进行视图变换和投影变换时MVP矩阵会改变顶点的位置信息。 输入: 顶点着色器输入部分主要是声明&…...

2024性价比家居好物有哪些?推荐五款值得每个家庭拥有的好物品牌!
每年双11的时候我都特别喜欢买一些家居好物,今年双11也不例外,经过我一两周的精心挑选,专门选了五款性价比高的家居好物,接下来给大家分享一下! 家居好物一、希亦ACE Pro内衣洗衣机 我买过、评测过的内衣洗衣机&#…...

字节青训-查找热点数据问题
问题描述 给你一个整数数组 nums 和一个整数 k,请你返回其中出现频率前 k 高的元素。请按升序排列。 1 < nums.length < 10^5k 的取值范围是 [1, 数组中不相同的元素的个数]题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合…...
Codeforces Round 981 (Div. 3) (A~F)
文章目录 A. Sakurako and Kosuke思路code B. Sakurako and Water思路code C. Sakurakos Field Trip思路code D. Kousukes Assignment思路code E. Sakurako, Kosuke, and the Permutation思路code F. Kosukes Sloth思路code Codeforces Round 981 (Div. 3) A. Sakurako and Ko…...

shell脚本实例(4)while实现1+...+100,linux新增用户
while实现1到100求和 #!/bin/bash/ s0 i1 #-le小于等于 while [ $i -le 100 ] dos$[ $s$i ]i$[ $i1 ] done echo $s echo $i 执行结果如下 修改用户名密码脚本 #!/bin/bash/ #提示用户输入用户名 read -p "请输入用户名:"username useradd $username #提…...
docker XML详解
下列为一个基本的运行docker镜像文件 {"Id": "62a82b0e69930e54c291095f632adde58dd0b247adba3a048385a55c87e38eba","Created": "2024-07-11T04:00:09.36091853Z","Path": "java","Args": ["-ja…...

web前端边框详解,弹性盒子的使用(仿写购物网页)
边框详解 1. 边框宽度(border - width) - 具体取值:可以是具体的长度值,如 px (像素)、 pt (点)、 em (相对单位)等。例如, border - width: 2px…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...

深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

【Linux】自动化构建-Make/Makefile
前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具:make/makfile 1.背景 在一个工程中源文件不计其数,其按类型、功能、模块分别放在若干个目录中,mak…...

AI语音助手的Python实现
引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...