创建线程那么容易,为什么非要让我使用线程池?(深深深入剖析)
一、概述
1、问题
先看我们遇到的问题:我们创建线程的方式很简单,new Thread(() -> {...}),就是因为这么简单粗暴的方式,才带来了致命的问题。首先线程的创建和销毁都是很耗时很浪费性能的操作,你用线程为了什么?为了就是异步,为了就是提升性能。简单的new三五个Thread还好,我需要一千个线程呢?你也for循环new1000个Thread吗?用完在销毁掉。那这一千个线程的创建和销毁的性能是很糟糕的!
2、解决
为了解决上述问题,线程池诞生了,线程池的核心思想就是:线程复用。也就是说线程用完后不销毁,放到池子里等着新任务的到来,反复利用N个线程来执行所有新老任务。这带来的开销只会是那N个线程的创建,而不是每来一个请求都带来一个线程的从生到死的过程。
二、线程池
1、概念
还说个鸡儿,上面的问题解决方案已经很通俗易懂了。针对特级小白我在举个生活的案例:
比如找工作面试,涉及到两个角色:面试官、求职者。求职者成千上万,每来一个求职者都要为其单独新找一个面试官来面试吗?显然不是,公司都有面试官池子,比如:A、B、C你们三就是这公司的面试官了,有人来面试你们三轮流面就行了。可能不是很恰当,含义就是说我并不需要为每个请求(求职者)都单独分配一个新的线程(面试官) ,而是我固定好几个线程,由他们几个来处理所有请求。不会反复创建销毁。
2、参数
2.1、源码
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {}
2.2、解释
- corePoolSize:核心线程数
线程池在完成初始化之后,默认情况下,线程池中不会有任何线程,线程池会等有任务来的时候再去创建线程。核心线程创建出来后即使超出了线程保持的存活时间配置也不会销毁,核心线程只要创建就永驻了,就等着新任务进来进行处理。
- maximumPoolSize:最大线程数
核心线程忙不过来且任务存储队列满了的情况下,还有新任务进来的话就会继续开辟线程,但是也不是任意的开辟线程数量,线程数(包含核心线程)达到maximumPoolSize后就不会产生新线程了,就会执行拒绝策略。
- keepAliveTime:线程保持的存活时间
如果线程池当前的线程数多于corePoolSize,那么如果多余的线程空闲时间超过keepAliveTime,那么这些多余的线程(超出核心线程数的那些线程)就会被回收。
- unit:线程保持的存活时间单位
比如:TimeUnit.MILLISECONDS、TimeUnit.SECONDS
- workQueue:任务存储队列
核心线程数满了后还有任务继续提交到线程池的话,就先进入workQueue。
workQueue通常情况下有如下选择:
LinkedBlockingQueue:无界队列,意味着无限制,其实是有限制,大小是int的最大值。也可以自定义大小。
ArrayBlockingQueue:有界队列,可以自定义大小,到了阈值就开启新线程(不会超过maximumPoolSize)。
SynchronousQueue:Executors.newCachedThreadPool();默认使用的队列。也不算是个队列,他不没有存储元素的能力。
一般都采取LinkedBlockingQueue,因为他也可以设置大小,可以取代ArrayBlockingQueue有界队列。
- threadFactory:当线程池需要新的线程时,会用threadFactory来生成新的线程
默认采用的是DefaultThreadFactory,主要负责创建线程。newThread()方法。创建出来的线程都在同一个线程组且优先级也是一样的。
- handler:拒绝策略,任务量超出线程池的配置限制或执行shutdown还在继续提交任务的话,会执行handler的逻辑。
默认采用的是AbortPolicy,遇到上面的情况,线程池将直接采取直接拒绝策略,也就是直接抛出异常。RejectedExecutionException
3、原理
3.1、原理
- 线程池刚启动的时候核心线程数为0
- 丢任务给线程池的时候,线程池会新开启线程来执行这个任务
- 如果线程数小于corePoolSize,即使工作线程处于空闲状态,也会创建一个新线程来执行新任务
- 如果线程数大于或等于corePoolSize,则会将任务放到workQueue,也就是任务队列
- 如果任务队列满了,且线程数小于maximumPoolSize,则会创建一个新线程来运行任务
- 如果任务队列满了,且线程数大于或等于maximumPoolSize,则直接采取拒绝策略
3.2、图解
3.3、举例
线程池参数配置:核心线程5个,最大线程数10个,队列长度为100。
那么线程池启动的时候不会创建任何线程,假设请求进来6个,则会创建5个核心线程来处理五个请求,另一个没被处理到的进入到队列。这时候有进来99个请求,线程池发现核心线程满了,队列还在空着99个位置,所以会进入到队列里99个,加上刚才的1个正好100个。这时候再次进来5个请求,线程池会再次开辟五个非核心线程来处理这五个请求。目前的情况是线程池里线程数是10个RUNNING状态的,队列里100个也满了。如果这时候又进来1个请求,则直接走拒绝策略。
3.4、源码
public void execute(Runnable command) { int c = ctl.get(); // workerCountOf(c):工作线程数 // worker数量比核心线程数小,直接创建worker执行任务 if (workerCountOf(c) < corePoolSize) { // addWorker里面负责创建线程且执行任务 if (addWorker(command, true)) return; c = ctl.get(); } // worker数量超过核心线程数,任务直接进入队列 if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); // 线程池状态不是RUNNING状态,说明执行过shutdown命令,需要对新加入的任务执行reject()操作。 // 这儿为什么需要recheck,是因为任务入队列前后,线程池的状态可能会发生变化。 if (! isRunning(recheck) && remove(command)) reject(command); // 这儿为什么需要判断0值,主要是在线程池构造方法中,核心线程数允许为0 else if (workerCountOf(recheck) == 0) addWorker(null, false); } // 如果线程池不是运行状态,或者任务进入队列失败,则尝试创建worker执行任务。 // 这儿有3点需要注意: // 1. 线程池不是运行状态时,addWorker内部会判断线程池状态 // 2. addWorker第2个参数表示是否创建核心线程 // 3. addWorker返回false,则说明任务执行失败,需要执行reject操作 else if (!addWorker(command, false)) reject(command); }
4、Executors
4.1、概念
首先这不是一个线程池,这是线程池的工具类,他能方便的为我们创建线程。但是阿里巴巴开发手册上说明不推荐用Executors创建线程池,推荐自己定义线程池。这是因为Executors创建的任何一种线程池都可能引发血案,具体是什么问题下面会说。
4.2、固定线程数
4.2.1、描述
核心线程数和最大线程数是一样的,所以称之为固定线程数。
其他参数配置默认为:永不超时(0ms),无界队列(LinkedBlockingQueue)、默认线程工厂(DefaultThreadFactory)、直接拒绝策略(AbortPolicy)。
4.2.2、api
Executors.newFixedThreadPool(n);
4.2.3、demo
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Description: 创建2个线程来执行10个任务。 * * @author TongWei.Chen 2020-07-09 21:28:34 */ public class ThreadPoolTest { public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(2); for (int i = 0; i < 10; i++) { // 从结果中可以发现线程name永远都是两个。不会有第三个。 executorService.execute(() -> System.out.println(Thread.currentThread().getName())); } } }
4.2.4、问题
问题就在于它是无界队列,队列里能放int的最大值个任务,并发巨高的情况下极大可能直接OOM了然后任务还在堆积,毕竟直接用的是jvm内存。所以建议自定义线程池,自己按照需求指定合适的队列大小,自定义拒绝策略将超出队列大小的任务放到对外内存做补偿,比如Redis。别把业务系统压垮就行。
4.2.5、源码
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor( // 核心线程数和最大线程数都是nThreads nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, // 无界队列!!!致命问题的关键所在。 new LinkedBlockingQueue<Runnable>()); }
4.3、单个线程
4.3.1、描述
核心线程数和最大线程数是1,内部默认的,不可更改,所以称之为单线程数的线程池。
类似于Executors.newFixedThreadPool(1);
其他参数配置默认为:永不超时(0ms),无界队列(LinkedBlockingQueue)、默认线程工厂(DefaultThreadFactory)、直接拒绝策略(AbortPolicy)。
4.3.2、api
Executors.newSingleThreadExecutor();
4.3.3、demo
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Description: 创建1个线程来执行10个任务。 * * @author TongWei.Chen 2020-07-09 21:28:34 */ public class ThreadPoolTest { public static void main(String[] args) { ExecutorService executorService = Executors.newSingleThreadExecutor(); for (int i = 0; i < 10; i++) { // 从结果中可以发现线程name永远都是pool-1-thread-1。不会有第二个出现。 executorService.execute(() -> System.out.println(Thread.currentThread().getName())); } } }
4.3.4、问题
同【4.2、固定线程数】的问题,都是无界队列惹的祸。
4.3.5、源码
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor( // 核心线程数和最大线程数都是1,写死的,客户端不可更改。 1, 1, 0L, TimeUnit.MILLISECONDS, // 无界队列!!!致命问题的关键所在。 new LinkedBlockingQueue<Runnable>())); }
4.4、带缓存的线程池
4.4.1、描述
他的功能是来个任务我就开辟个线程去处理,不会进入队列,SynchronousQueue队列也不带存储元素的功能。那这意味着来一亿个请求就会开辟一亿个线程去处理,keepAliveTime为60S,意味着线程空闲时间超过60S就会被杀死;这就叫带缓存功能的线程池。
核心线程数是0,最大线程数是int的最大值,内部默认的,不可更改。
其他参数配置默认为:1min超时(60s),SynchronousQueue队列、默认线程工厂(DefaultThreadFactory)、直接拒绝策略(AbortPolicy)。
4.4.2、api
Executors.newCachedThreadPool();
4.4.3、demo
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Description: 创建个带缓存功能的线程池来执行10个任务。 * * @author TongWei.Chen 2020-07-09 21:28:34 */ public class ThreadPoolTest { public static void main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) { // 从结果中可以发现线程name有10个。也就是有几个任务就会开辟几个线程。 executorService.execute(() -> System.out.println(Thread.currentThread().getName())); } } }
4.4.4、问题
问题就在于他的最大线程数是int的最大值,因为他内部采取的队列是SynchronousQueue,这个队列没有容纳元素的能力,这将意味着只要来请求我就开启线程去工作,巅峰期能创建二十几亿个线程出来工作,你自己想想多么可怕!!!
4.4.5、源码
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor( // 核心线程数是0,最大线程数都是Integer.MAX_VALUE,这个可致命了!!! 0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
4.5、有调度功能的线程池
4.5.1、描述
RocketMQ内部大量采用了此种线程池来做心跳等任务。
核心线程数手动传进来,最大线程数是Integer.MAX_VALUE,最大线程数是内部默认的,不可更改。
其他参数配置默认为:永不超时(0ns),带延迟功能的队列(DelayedWorkQueue)、默认线程工厂(DefaultThreadFactory)、直接拒绝策略(AbortPolicy)。
4.5.2、api
Executors.newScheduledThreadPool(n);
4.5.3、demo
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Description: 创建个带调度功能的线程池来执行任务。 * * @author TongWei.Chen 2020-07-09 21:28:34 */ public class ThreadPoolTest { public static void main(String[] args) { ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2); // 五秒一次 scheduledExecutorService.schedule(() -> System.out.println(Thread.currentThread().getName()), 5, TimeUnit.SECONDS); // 首次五秒后执行,其次每隔1s执行一次 scheduledExecutorService.scheduleAtFixedRate(() -> System.out.println(Thread.currentThread().getName()), 5, 1, TimeUnit.SECONDS); } }
4.5.4、问题
【同4.4、带缓存的线程池的问题】
问题就在于他的最大线程数是int的最大值,这将意味海量并发期能创建二十几亿个线程出来工作,你自己想想多么可怕!!!
4.5.5、源码
public ScheduledThreadPoolExecutor(int corePoolSize) { // 致命的问题跟newCachedThreadPool一样,最大线程数能开到几十亿(Integer.MAX_VALUE)!!! super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue()); }
4.6、停止线程
4.6.1、shutdown
平缓的结束线程池,比如当前线程池还在执行任务,还没执行完,这时候执行了shutdown的话,线程池并不会立即停止工作,而是会等待线程池中的任务都执行完成后才会shutdown掉,但是如果执行shutdown了,外界还在继续提交任务到线程池,那么线程池会直接采取拒绝策略。
4.6.2、isShutdown
判断线程池是否已经shutdown。
4.6.3、shutdownNow
暴力结束线程池。不管你当前线程池有没有任务在执行,队列里有没有堆积消息,我都直接让线程池挂掉。但是他的返回值是队列里那些未被执行的任务。有需要的可以记录下log啥的。
4.7、疑问
这几种线程池为什么要采取不一样的队列?比如newFixedThreadPool为什么采取LinkedBlockingQueue,而newCachedThreadPool又为什么采取SynchronousQueue?
因为newFixedThreadPool线程数量有限,他又不想丢失任务,只能采取无界队列,而newCachedThreadPool的话本身自带int最大值个线程数,所以没必要用无界队列,他的宗旨就是我有线程能处理,不需要队列。
5、总结几个问题
1、线程池的状态
- RUNNING:接受新任务并处理排队任务。
- SHUTDOWN:不接受新任务,但是会处理排队任务。【见:停止线程的4.6.1、shutdown】
- STOP:不接受新任务,也不处理排队任务,并中端正在进行的任务。
- TIDYING:所有任务都已经完事,工作线程为0的时候 ,线程会进入这个状态并执行terminate()钩子方法。
- TERMINATED:terminate()钩子方法运行完成。
2、线程池自动创建还是手动?
那肯定是手动了,因为Executors自动创建的那些线程池都存在致命的问题。手动创建线程池我们能自己控制线程数大小以及队列大小,还可以指定组名称等等个性化配置。重点不会出现致命问题,风险都把控在我们手里。
3、线程数多少合适?
- CPU密集型(比如加密、各种复杂计算等):建议设置为CPU核数+1。
- 耗时IO操作(比如读写数据库,压缩解压缩大文件等等):一般会设置CPU核数的2倍。当然也有个很牛X的计算公式:线程数=CPU核数 *(1+平均等待时间/平均工作时间)
4、before&after
在线程执行前后可以通过两个方法来进行打印log或其他工作。
源码如下:
// 执行前的before beforeExecute(wt, task); Throwable thrown = null; try { // 真正执行 task.run(); } catch (RuntimeException x) { thrown = x; throw x; } catch (Error x) { thrown = x; throw x; } catch (Throwable x) { thrown = x; throw new Error(x); } finally { // 执行完成后after afterExecute(task, thrown); }
6、核心源码(全)
1、常用变量的解释
// 1. `ctl`,可以看做一个int类型的数字,高3位表示线程池状态,低29位表示worker数量 private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); // 2. `COUNT_BITS`,`Integer.SIZE`为32,所以`COUNT_BITS`为29 private static final int COUNT_BITS = Integer.SIZE - 3; // 3. `CAPACITY`,线程池允许的最大线程数。1左移29位,然后减1,即为 2^29 - 1 private static final int CAPACITY = (1 << COUNT_BITS) - 1; // runState is stored in the high-order bits // 4. 线程池有5种状态,按大小排序如下:RUNNING < SHUTDOWN < STOP < TIDYING < TERMINATED private static final int RUNNING = -1 << COUNT_BITS; private static final int SHUTDOWN = 0 << COUNT_BITS; private static final int STOP = 1 << COUNT_BITS; private static final int TIDYING = 2 << COUNT_BITS; private static final int TERMINATED = 3 << COUNT_BITS; // Packing and unpacking ctl // 5. `runStateOf()`,获取线程池状态,通过按位与操作,低29位将全部变成0 private static int runStateOf(int c) { return c & ~CAPACITY; } // 6. `workerCountOf()`,获取线程池worker数量,通过按位与操作,高3位将全部变成0 private static int workerCountOf(int c) { return c & CAPACITY; } // 7. `ctlOf()`,根据线程池状态和线程池worker数量,生成ctl值 private static int ctlOf(int rs, int wc) { return rs | wc; } /* * Bit field accessors that don't require unpacking ctl. * These depend on the bit layout and on workerCount being never negative. */ // 8. `runStateLessThan()`,线程池状态小于xx private static boolean runStateLessThan(int c, int s) { return c < s; } // 9. `runStateAtLeast()`,线程池状态大于等于xx private static boolean runStateAtLeast(int c, int s) { return c >= s; }
2、构造方法
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { // 基本类型参数校验 if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException(); // 空指针校验 if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; // 根据传入参数`unit`和`keepAliveTime`,将存活时间转换为纳秒存到变量`keepAliveTime `中 this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler; }
3、提交执行task的过程
public void execute(Runnable command) { if (command == null) throw new NullPointerException(); /* * Proceed in 3 steps: * * 1. If fewer than corePoolSize threads are running, try to * start a new thread with the given command as its first * task. The call to addWorker atomically checks runState and * workerCount, and so prevents false alarms that would add * threads when it shouldn't, by returning false. * * 2. If a task can be successfully queued, then we still need * to double-check whether we should have added a thread * (because existing ones died since last checking) or that * the pool shut down since entry into this method. So we * recheck state and if necessary roll back the enqueuing if * stopped, or start a new thread if there are none. * * 3. If we cannot queue task, then we try to add a new * thread. If it fails, we know we are shut down or saturated * and so reject the task. */ int c = ctl.get(); // worker数量比核心线程数小,直接创建worker执行任务 if (workerCountOf(c) < corePoolSize) { if (addWorker(command, true)) return; c = ctl.get(); } // worker数量超过核心线程数,任务直接进入队列 if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); // 线程池状态不是RUNNING状态,说明执行过shutdown命令,需要对新加入的任务执行reject()操作。 // 这儿为什么需要recheck,是因为任务入队列前后,线程池的状态可能会发生变化。 if (! isRunning(recheck) && remove(command)) reject(command); // 这儿为什么需要判断0值,主要是在线程池构造方法中,核心线程数允许为0 else if (workerCountOf(recheck) == 0) addWorker(null, false); } // 如果线程池不是运行状态,或者任务进入队列失败,则尝试创建worker执行任务。 // 这儿有3点需要注意: // 1. 线程池不是运行状态时,addWorker内部会判断线程池状态 // 2. addWorker第2个参数表示是否创建核心线程 // 3. addWorker返回false,则说明任务执行失败,需要执行reject操作 else if (!addWorker(command, false)) reject(command); }
4、addworker源码解析
private boolean addWorker(Runnable firstTask, boolean core) { retry: // 外层自旋 for (;;) { int c = ctl.get(); int rs = runStateOf(c); // 这个条件写得比较难懂,我对其进行了调整,和下面的条件等价 // (rs > SHUTDOWN) || // (rs == SHUTDOWN && firstTask != null) || // (rs == SHUTDOWN && workQueue.isEmpty()) // 1. 线程池状态大于SHUTDOWN时,直接返回false // 2. 线程池状态等于SHUTDOWN,且firstTask不为null,直接返回false // 3. 线程池状态等于SHUTDOWN,且队列为空,直接返回false // Check if queue empty only if necessary. if (rs >= SHUTDOWN && ! (rs == SHUTDOWN && firstTask == null && ! workQueue.isEmpty())) return false; // 内层自旋 for (;;) { int wc = workerCountOf(c); // worker数量超过容量,直接返回false if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize)) return false; // 使用CAS的方式增加worker数量。 // 若增加成功,则直接跳出外层循环进入到第二部分 if (compareAndIncrementWorkerCount(c)) break retry; c = ctl.get(); // Re-read ctl // 线程池状态发生变化,对外层循环进行自旋 if (runStateOf(c) != rs) continue retry; // 其他情况,直接内层循环进行自旋即可 // else CAS failed due to workerCount change; retry inner loop } } boolean workerStarted = false; boolean workerAdded = false; Worker w = null; try { w = new Worker(firstTask); final Thread t = w.thread; if (t != null) { final ReentrantLock mainLock = this.mainLock; // worker的添加必须是串行的,因此需要加锁 mainLock.lock(); try { // Recheck while holding lock. // Back out on ThreadFactory failure or if // shut down before lock acquired. // 这儿需要重新检查线程池状态 int rs = runStateOf(ctl.get()); if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null)) { // worker已经调用过了start()方法,则不再创建worker if (t.isAlive()) // precheck that t is startable throw new IllegalThreadStateException(); // worker创建并添加到workers成功 workers.add(w); // 更新`largestPoolSize`变量 int s = workers.size(); if (s > largestPoolSize) largestPoolSize = s; workerAdded = true; } } finally { mainLock.unlock(); } // 启动worker线程 if (workerAdded) { t.start(); workerStarted = true; } } } finally { // worker线程启动失败,说明线程池状态发生了变化(关闭操作被执行),需要进行shutdown相关操作 if (! workerStarted) addWorkerFailed(w); } return workerStarted; }
5、线程池worker任务单元
private final class Worker extends AbstractQueuedSynchronizer implements Runnable{ /** * This class will never be serialized, but we provide a * serialVersionUID to suppress a javac warning. */ private static final long serialVersionUID = 6138294804551838833L; /** Thread this worker is running in. Null if factory fails. */ final Thread thread; /** Initial task to run. Possibly null. */ Runnable firstTask; /** Per-thread task counter */ volatile long completedTasks; /** * Creates with given first task and thread from ThreadFactory. * @param firstTask the first task (null if none) */ Worker(Runnable firstTask) { setState(-1); // inhibit interrupts until runWorker this.firstTask = firstTask; // 这儿是Worker的关键所在,使用了线程工厂创建了一个线程。传入的参数为当前worker this.thread = getThreadFactory().newThread(this); } /** Delegates main run loop to outer runWorker */ public void run() { runWorker(this); } // 省略代码... }
6、核心线程执行逻辑-runworker
final void runWorker(Worker w) { Thread wt = Thread.currentThread(); Runnable task = w.firstTask; w.firstTask = null; // 调用unlock()是为了让外部可以中断 w.unlock(); // allow interrupts // 这个变量用于判断是否进入过自旋(while循环) boolean completedAbruptly = true; try { // 这儿是自旋 // 1. 如果firstTask不为null,则执行firstTask; // 2. 如果firstTask为null,则调用getTask()从队列获取任务。 // 3. 阻塞队列的特性就是:当队列为空时,当前线程会被阻塞等待 while (task != null || (task = getTask()) != null) { // 这儿对worker进行加锁,是为了达到下面的目的 // 1. 降低锁范围,提升性能 // 2. 保证每个worker执行的任务是串行的 w.lock(); // If pool is stopping, ensure thread is interrupted; // if not, ensure thread is not interrupted. This // requires a recheck in second case to deal with // shutdownNow race while clearing interrupt // 如果线程池正在停止,则对当前线程进行中断操作 if ((runStateAtLeast(ctl.get(), STOP) || (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) && !wt.isInterrupted()) wt.interrupt(); // 执行任务,且在执行前后通过`beforeExecute()`和`afterExecute()`来扩展其功能。 // 这两个方法在当前类里面为空实现。 try { beforeExecute(wt, task); Throwable thrown = null; try { task.run(); } catch (RuntimeException x) { thrown = x; throw x; } catch (Error x) { thrown = x; throw x; } catch (Throwable x) { thrown = x; throw new Error(x); } finally { afterExecute(task, thrown); } } finally { // 帮助gc task = null; // 已完成任务数加一 w.completedTasks++; w.unlock(); } } completedAbruptly = false; } finally { // 自旋操作被退出,说明线程池正在结束 processWorkerExit(w, completedAbruptly); } }
7、自建线程池注意点
- 阻塞任务队列数
- 线程池的名字,最好跟业务相关
- 核心线程池大小,看业务实际情况。可以参考【线程数多少合适?】
- 最大线程池大小,看业务实际情况。可以参考【线程数多少合适?】
- 拒绝策略,我个人一般都是记录log,如果主要的业务我会根据log做补偿。
比如:
ThreadPoolExecutor executor = new ThreadPoolExecutor(CPU核数 + 1, 2 * CPU核数 + 1, 5, TimeUnit.SECONDS, new ArrayBlockingQueue<>(2000), // 线程池名字pay-account new DefaultThreadFactory("pay-account"), (r1, executor) -> { // 记录log 重新入队列做补偿 });
END
关注转发就是最大的支持哦
// 需要资料可以添加xuanwo008
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
相关文章
- NO.1-SAP S4 HANA Cloud实施方法论(1)
SAP S4 HANA Cloud是SAP最新的和最具创新性的软件即服务(SaaS)ERP产品,其包含以财务为核心的制造、销售、供应链、专业服务等多个模块如下图所示,部署SAP S4 HANA Cloud(以下简称S4HC)的实施时间是以几周为单位衡量的,而不是像以前OP版本需要几个月甚至几年的部署时间,…...
2024/4/16 0:58:07 - 陷波滤波器设计
飞控课程笔记(二) (https://zhuanlan.zhihu.com/p/66962045 across说的课程)在飞控领域中,主要针对飞行器在某一个高频点幅值较大,换句话来说,就是常见的飞机有共振的现象时。首先考虑通过机械减震或IMU减震来消除这种现象,若实际很难做到就考虑软件方面处理。要使用…...
2024/4/16 0:58:22 - js新入小白的练习题
js新入小白的练习题 程序有三大结构:1. 顺序结构2. 条件结构3. 循环结构条件结构-if语句:if(表达式1){语句1}if(表达式2){语句2}else if{语句3}练习:请输入一个年份,判断这个年份是平年还是闰年。var year = prompt("请输入年份");//请用户输入if (year % 4 …...
2024/4/16 0:57:47 - 02-作业
一 什么是CSS?Cascading Style Sheet 层叠样式表 作用:布局 美化 特点:对缩进或换行不敏感,写的时候建议每一个属性都放一行,后期可能通过CSS压缩(可以减少文件体积有利于性能优化)工具进行压缩(让CSS属性变成一行)除了最后一条属性可以不加分号外,其它的属性都要加…...
2024/4/16 1:17:29 - 微信小程序vant 输入框问题
在开发时候需要添加评论,点击的时候从底部弹起,效果如下图开发过程中遇到的问题有如下几个: 1.van-field 搭配 van-popup 个别手机弹出后会导致输入框位置乱跳,问题原因是van-popup多次弹出数据渲染会有一定问题 2.van-field 搭配 van-overlay(遮罩) 遮罩弹出太慢,手机性…...
2024/4/17 7:24:12 - 线程---join()
public class BlockJoin {public static void main(String[] args) {new Thread(new father()).start();} }class father implements Runnable{@Overridepublic void run() {System.out.println("老爸想吸烟");System.out.println("老爸给儿子钱,儿子去买烟&qu…...
2024/4/30 4:30:03 - jeecg框架学习纪录 【 阿里云短信发送验证码 平台配置和项目中使用】
文章目录jeecg项目效果展示短息通知页面入口代码中调用短信api 配置和代码API中的重要参数配置项:阿里控制台注册注册签名注册短信模板 阿里云短信发送验证码配置和项目使用jeecg 第一次接触jeecg框架后,对这个框架就很喜欢,Jeecg是一款基于SpringBoot+代码生成器的快速开…...
2024/5/2 21:11:08 - 浅谈Spring AOP的原理和应用
浅谈Spring AOP的原理和应用 1.AOP简介 Aop(Aspect Oriented Programming)大家应该都知道这是面向切面编程思想,主要能够为我们在不影响原来的功能的前提,为软件横向拓展功能。简单来说,把对象中一些公用的行为抽取出来,减少代码冗余性,还可以将业务代码和系统功能代码分…...
2024/4/16 0:58:38 - 最新校招京东、百度、头条算法面试真题分享
1 .京东面试经历 面试的京东的商品推荐的算法岗,在北辰大厦(奥森旁边),面试难度总体来说比较简单。 ①:到公司之后先做了一个小时的笔试题目,包括四个简答题和两个编程题,简答题主要是 C语言相关的。 Map和Set的插入和查找的复杂度是多少,Set是否可以存储类 递归和循环…...
2024/5/6 19:09:48 - 数据结构(二):二叉搜索树(Binary Search Tree)
二分法猜数字的游戏应该每个人都知道,通过对猜测数字“大了”、“小了”的情况判断,来猜出最终的数字。序列范围为 n 的集合,复杂度为 O(log_2 n),即最多需要 log_2 n 次可以猜到最终数字。 二分法的查找过程是,在一个有序的序列中,每次都会选择有效范围中间位置的元素作…...
2024/4/16 0:59:49 - Leetcode99 恢复二叉搜索树
题目:二叉搜索树中的两个节点被错误地交换。请在不改变其结构的情况下,恢复这棵树。 思路:中序遍历。保存前一个节点。当前一个节点大于当前节点,说明错误发生,记录前一个节点值当第一个节点被记录后,继续递归,找到最后一个该情况,记录当前节点值。交换两个节点 代码:…...
2024/4/1 3:36:39 - MyBatis根据客户编号查询客户信息
1.MySQL数据库中,创建一个名为mybatis的数据库,在此数据库中创建一个t_customer表,同时预先插入几条数据。INSERT INTO t_customer VALUES (1, joy, doctor, 13745874578); 2.在Eclipse中,创建一个名为chapter06的Web项目,将MyBatis的核心JAR包、lib目录中的依赖JAR包,以…...
2024/4/16 0:58:48 - springboot logback日志打印配置
坑 最近看到日志打印,想学习下。其中也遇到了不少坑,经过不断的填坑,现已经整理了一个比较完善的配置文件出来了,小记一下~ 1.日志错误日志分离 2.每天一个日志文件 3.异步打印日志 一、配置文件logback-spring.xml(logback.xml) <?xml version="1.0" encodi…...
2024/4/19 10:43:22 - http转https证书的时候报错
http转https证书的时候报错 [http-nio-8066-exec-6] INFO o.a.c.h.Http11Processor - [log,175] - Error parsing HTTP request header Error parsing HTTP request header Note: further occurrences of HTTP request parsing errors will be logged at DEBU G level. java.l…...
2024/4/16 0:59:03 - GitHub创建分支切换分支
管理分支 1、查看分支 2、查看本地分支 使用 git branch命令,如下: $ git branchmaster 标识的是你当前所在的分支。2、查看远程分支 命令如下: git branch -r3、查看所有分支 命令如下: git branch -a2、本地创建新的分支 命令如下: git branch [branch name]例如: git …...
2024/4/16 0:59:03 - 用CAPL通过RS232远程控制ALR3220程控电源
用CAPL通过RS232远程控制ALR3220程控电源1. ALR3220程控电源2. ALR3220 远程控制命令3. 用CAPL控制ALR32203.1 首先需要用Panel Designer设计一个控制面板![在这里插入图片描述](https://img-blog.csdnimg.cn/20200711160738847.JPG?x-oss-process=image/watermark,type_ZmFuZ…...
2024/4/20 12:44:51 - Python(3)整型和字符串的魔法(一)
Pycharm用法:To join two lines into one and remove unnecessary spaces, press Ctrl+Shift+J. 整型的魔法: int用法,将字符串转换成数字; a = "123" b = int(a) b = b+1000 print(b)运行结果: 1123 a = "123m" b = int(a) b = b+1000 print(b)运行结…...
2024/4/18 11:49:26 - Android ScrollView 实现小说阅读界面自动滚屏
前言 最近在做一个阅读器,准备实现一个自动滚屏来方便阅读 实现 在xml中放入一个ScrollView 滑动条,滑动条里面放一个文本框<RelativeLayoutandroid:id="@+id/relativeLayout"android:layout_width="match_parent"android:layout_height="match_…...
2024/4/29 3:20:50 - C Primer Plus 第6版 第8章 练习答案
我的博客主要记录一下自己的学习代码过程。 大家想看完整的答案的话,这里推荐xiaojimmychen的完整的答案 编译器为VS2019 第八章的运行结果如下: 8.1 #include<stdio.h> #include <stdlib.h> int main(void) {int x, y;x = y = 0;printf("请输入字符串:\n&…...
2024/4/16 0:59:13 - M5 数据拼接和特征工程
baseline:sales_train calendar sell_prices数据拼接成以下形式时间移位特征 把demand后移28,29,30天作为三个f"shift_t{val}" 把时移28天后,滑动窗口为7, 30, 60, 90, 180的标准差和均值作为f"rolling_std_t{val}" f"rolling_mean_t{val}&qu…...
2024/4/1 3:36:29
最新文章
- 扩展学习|一文读懂知识图谱
一、知识图谱的技术实现流程及相关应用 文献来源:曹倩,赵一鸣.知识图谱的技术实现流程及相关应用[J].情报理论与实践,2015, 38(12):127-132. (一)知识图谱的特征及功能 知识图谱是为了适应新的网络信息环境而产生的一种语义知识组织和服务的方…...
2024/5/6 20:15:42 - 梯度消失和梯度爆炸的一些处理方法
在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言,在此感激不尽。 权重和梯度的更新公式如下: w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...
2024/5/6 9:38:23 - 解析大语言模型训练三阶段
大语言模型的训练过程一般包括3个阶段:预训练(Pre-training)、SFT(有监督的微调,Supervised-Finetuning)以及RLHF(基于人类反馈的强化学习,Reinforcement Learning from Human Feedb…...
2024/5/5 18:48:29 - Redis Stack十部曲之三:理解Redis Stack中的数据类型
文章目录 前言String字符串作为计数器限制 List限制列表阻塞列表自动创建和删除聚合类型键限制 Set限制 Hash限制 Sorted Set范围操作字典操作更新分数 JSON路径限制 BitMapBitfieldProbabilisticHyperLogLogBloom filterCuckoo filtert-digestTop-KCount-min sketchConfigurat…...
2024/5/4 13:36:16 - 【外汇早评】美通胀数据走低,美元调整
原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...
2024/5/4 23:54:56 - 【原油贵金属周评】原油多头拥挤,价格调整
原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...
2024/5/4 23:54:56 - 【外汇周评】靓丽非农不及疲软通胀影响
原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...
2024/5/4 23:54:56 - 【原油贵金属早评】库存继续增加,油价收跌
原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...
2024/5/6 9:21:00 - 【外汇早评】日本央行会议纪要不改日元强势
原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...
2024/5/4 23:54:56 - 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响
原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...
2024/5/4 23:55:05 - 【外汇早评】美欲与伊朗重谈协议
原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...
2024/5/4 23:54:56 - 【原油贵金属早评】波动率飙升,市场情绪动荡
原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...
2024/5/4 23:55:16 - 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试
原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...
2024/5/4 23:54:56 - 【原油贵金属早评】市场情绪继续恶化,黄金上破
原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...
2024/5/6 1:40:42 - 【外汇早评】美伊僵持,风险情绪继续升温
原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...
2024/5/4 23:54:56 - 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势
原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...
2024/5/4 23:55:17 - 氧生福地 玩美北湖(上)——为时光守候两千年
原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...
2024/5/4 23:55:06 - 氧生福地 玩美北湖(中)——永春梯田里的美与鲜
原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...
2024/5/4 23:54:56 - 氧生福地 玩美北湖(下)——奔跑吧骚年!
原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...
2024/5/4 23:55:06 - 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!
原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...
2024/5/5 8:13:33 - 「发现」铁皮石斛仙草之神奇功效用于医用面膜
原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...
2024/5/4 23:55:16 - 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者
原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...
2024/5/4 23:54:58 - 广州械字号面膜生产厂家OEM/ODM4项须知!
原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...
2024/5/4 23:55:01 - 械字号医用眼膜缓解用眼过度到底有无作用?
原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...
2024/5/4 23:54:56 - 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...
解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...
2022/11/19 21:17:18 - 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。
%读入6幅图像(每一幅图像的大小是564*564) f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...
2022/11/19 21:17:16 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...
win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...
2022/11/19 21:17:15 - 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...
有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...
2022/11/19 21:17:14 - win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...
置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...
2022/11/19 21:17:13 - 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...
Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...
2022/11/19 21:17:12 - 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...
有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...
2022/11/19 21:17:11 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...
今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...
2022/11/19 21:17:10 - 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...
只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...
2022/11/19 21:17:09 - 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?
原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...
2022/11/19 21:17:08 - 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...
关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...
2022/11/19 21:17:05 - 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...
钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...
2022/11/19 21:17:05 - 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...
前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...
2022/11/19 21:17:04 - 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...
本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...
2022/11/19 21:17:03 - 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...
许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...
2022/11/19 21:17:02 - 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...
配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...
2022/11/19 21:17:01 - 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...
不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...
2022/11/19 21:17:00 - 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...
当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...
2022/11/19 21:16:59 - 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...
我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢࿰…...
2022/11/19 21:16:58 - 如何在iPhone上关闭“请勿打扰”
Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...
2022/11/19 21:16:57