由于JVM运行程序的实体是线程,每个线程创建时JVM都会为其创建一个工作内存(栈空间),工作内存是每个线程的私有数据区域,而java内存模型中规定所有变量都存储在主内存,主内存是共享内存区域,所有线程都可以访问,但线程对变量的操作(读取赋值等)必须在工作内存中进行,首先将变量从主内存拷贝到自己的工作内存空间,然后对变量进行操作,操作完成后再将变量写回主内存,各个线程中的工作内存存储着主内存中的变量副本拷贝,因此不同的线程间无法访问对方的工作内存,线程之间的传值必须通过主内存来完成

AQS提供了一种实现阻塞锁和一系列依赖FIFO等待队列的同步器的框架

img

一、多线程

1、线程的生命周期

新建(new)—>就绪(Runnable)—>运行(Running)—>阻塞(Blocked)—>死亡(Dead)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0d3BkgAq-1592830132707)(…/img/多线程.png)]

2、你是如何理解多线程的?

  1. 多线程定义:

    多线程是指从硬件或软件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多个线程,进而提升整体的处理性能。

  2. 多线程由来:

    因为单个线程的处理能力低下。打个比方,一个人去搬砖与几个人去搬砖,一个人只能同时搬一车,但是几个人可以同时一起搬多个车。

  3. 多线程实现:

    在 Java 中,实现多线程主要是依靠JUC包下的四种方式:

    1. 直接继承Thread类;
    2. 实现 Runnable 接口;
    3. 实现 Callable 接口配合 FutureTask 对象使用; Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。
    4. 使用线程池。如 Executors 工具类。
  4. 需要注意的问题:

    进程:一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个线程,进程也是程序的一次执行过程,是系统运行程序的基本单位,系统运行一个程序即一个进程从创建、运行到消亡的过程

    线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程至少有一个线程,一个进程中可以有多个线程,这个程序也可以称为多线程程序。

3、多线程编程中的三个核心概念

  1. 原子性

    ​ 与数据库事务的原子性概念差不多,即一个操作(有可能包含有多个子操作)在执行时,要么全部成功(生效),要么全都不成功(都不生效)。

    ​ 如转账问题:包含减钱加钱两个子操作,要么这两个操作一起成功,要么一起失败。

  2. 可见性

    ​ 可见性是指,当多个线程并发访问共享变量时,一个线程对共享变量的修改,其它线程能够立即看到。

    ​ 可见性问题是由硬件机制引起的:CPU从主内存中读数据的效率相对来说不高,现在主流的计算机中,都有几级缓存。每个线程在读取共享变量时,都会将该变量加载进其所在CPU的高速缓存里,修改该变量后,CPU会立即更新该缓存,但并不一定会立即将其写回主内存(实际上写回主内存的时间不可预期)。此时其它线程(尤其是不在同一个CPU上执行的线程)访问该变量时,从主内存中读到的就是旧的数据,而非是更新后的数据。

  3. 顺序性

    顺序性指的是,**程序执行的顺序按照代码的先后顺序执行。**在实际处理中,处理器为了提高程序整体的执行效率,可能会对代码进行优化,其中的一项优化方式就是调整代码的执行顺序,按照更高效的顺序执行代码。

4、线程之间的通信方式

  1. 等待通知机制有:

    • wait()

      ​ t.wait():让调用此方法的线程进入等待状态,释放CUP并释放持有的锁,只有notify()/notifyAll()可以唤醒。

    • notify()/notifyAll()

      ​ notify():唤醒等待队列中的一个线程,使其获得锁进行访问。

      ​ notifyAll():唤醒等待队列中等待该对象锁的全部线程,让其竞争去获得锁。

    • join()

      ​ t.join()方法阻塞调用此方法的线程(calling thread),直到线程t完成,此线程再继续;通常用于在main()主线程内,等待其它线程完成再结束main()主线程。

    • interrupted():

      ​ interrupt():该方法是用于中断线程的,调用该方法的线程的状态将被置为"中断"状态。

      注意:**调用interrupt()方法仅仅是在当前线程中打了一个停止的标记,并不是真的停止线程,需要用户自己去监视线程的状态并做处理。**这一方法实际上完成的是,在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞的状态。更确切的说,如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞,那么,它将接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态。

      interrupted():测试当前线程(当前线程是指运行interrupted()方法的线程)是否已经中断,且清除中断状态。

      isInterrupted():测试线程(调用该方法的线程)是否已经中断,不清除中断状态

      interrupted()、isInterrupted()区别:

      ​ interrupted 是作用于当前线程,isInterrupted 是作用于调用该方法的线程对象所对应的线程。(线程对象对应的线程不一定是当前运行的线程。例如我们可以在A线程中去调用B线程对象的isInterrupted方法。)

      这两个方法最终都会调用同一个方法-----isInterrupted(boolean ClearInterrupted),只不过参数ClearInterrupted固定为一个是true,一个是false;下面是该方法,该方法是一个本地方法。

  2. 并发同步工具有:

    • synchronized
    • lock
    • CountDownLatch
    • CyclicBarrier
    • Semaphore

5、锁

1、定义

​ 锁是在不同线程竞争资源的情况下用来分配不同线程执行方式的同步控制工具,只有线程获取到锁之后才能访问同步代码,否则需等待其他线程使用结束后释放锁

  • 锁消除:jvm即时编译器运行时,对一些代码上要求同步,但是被检测到不可能存在共享数据竞争的锁进行消除
  • 锁粗化:原则上,同步块的作用范围尽量小,但是如果一系列的连续操作对同一个对象反复的加锁和解锁,导致不必要的性能消耗,其实就是增大锁的作用域

2、锁分类

​ 锁主要存在四种状态:无锁、偏向锁、轻量级锁、重量级锁,会随着竞争而逐渐升级

  1. 无锁

  2. 偏向锁:目的在于消除数据在无竞争情况下的同步原语,进一步提高程序的运行性能,偏向锁会偏向于第一个获得它的线程,如果接下来执行过程中,该锁没有被其他线程获取,那持有偏向锁的线程将永远不同步

    • 当锁第一次被线程获取时候,线程会使用CAS操作吧线程的ID记录在对象的Mark Word中,同时置偏向标志位1,以后线程再进入和退出代码块不需要CAS操作来加锁和解锁,只需简单测试一下Mark Word里是否存储着当前线程的ID,测试成功表示线程已获得锁
  3. 轻量级锁(自旋锁):是指当前锁是偏向锁的时候,被另外的线程所访问,那么偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,从而提高性能。

    1. 在代码进入同步块的时候,如果同步对象锁状态为无锁状态(锁标志位为 01 状态,是否为偏向锁为 0 ),虚拟机首先将在当前线程的栈帧中建立一个名为锁记录(Lock Record)的空间,用于存储锁对象目前的 Mark Word 的拷贝,然后拷贝对象头中的 Mark Word 复制到锁记录中。
    2. 拷贝成功后,虚拟机将使用 CAS 操作尝试将对象的 Mark Word 更新为指向 Lock Record 的指针,并将 Lock Record里的 owner 指针指向对象的 Mark Word。
    3. 如果这个更新动作成功了,那么这个线程就拥有了该对象的锁,并且对象Mark Word的锁标志位设置为 00 ,表示此对象处于轻量级锁定状态。
    4. 如果这个更新操作失败了,虚拟机首先会检查对象的 Mark Word 是否指向当前线程的栈帧,如果是就说明当前线程已经拥有了这个对象的锁,那就可以直接进入同步块继续执行。否则说明多个线程竞争锁,轻量级锁就要膨胀为重量级锁,锁标志的状态值变为10 ,Mark Word中存储的就是指向重量级锁(互斥量)的指针,后面等待锁的线程也要进入阻塞状态。
  4. 重量级锁:重量级锁也就是通常说 synchronized 的对象锁,锁标识位为10,其中指针指向的是 monitor
    对象(也称为管程或监视器锁)的起始地址。

    img

3、synchronized(方法和代码块)

隐式锁,通常和wait(),notify(),notifyAll()一块使用。

原理:在JVM级别实现

  • 同步代码块会在生成的字节码中加上monitorenter和monitorexit,任何对象都有一个monitor与之相关联,当且一个monitor被持有之后,他将处于锁定状态。
  • 同步方法是在Class文件的方法表中将该方法的accessflags字段中的sync标志位设为1,表示该方法是同步方法并调用该方法的对象或该方法所属的Class在jvm的内部对象表示klass作为锁对象

关联使用

  • wait:释放占有的对象锁,释放CPU,进入等待队列只能通过notify/notifyAll继续该线程。
  • sleep:释放CPU,但是不释放占有的对象锁,可以在sleep结束后自动继续该线程。
  • notify:唤醒等待队列中的一个线程,使其获得锁进行访问。
  • notifyAll:唤醒等待队列中等待该对象锁的全部线程,让其竞争去获得锁。

4、lock

​ 显示锁,拥有synchronize相同的语义,但是添加一些其他特性,如中断锁等候定时锁等候。可以使用lock代替synchronize,但必须手动加锁和释放锁。通过lock()手动加锁,通过unlock()方法手动释放锁,unlock()方法需要放到finally里保证锁能释放。

  1. synchronized与lock的区别

    synchronized lock
    性能 稍差【竞争激烈时】/差不多【竞争不激烈】 好【竞争激烈时】/差不多【竞争不激烈】
    用法 普通同步方法:锁是当前实例对象。静态同步方法,锁是当前类的class对象。同步代码块:锁是括号里的对象。 通过代码实现,需要手动上锁与释放,提供了多样化的同步,如公平锁、有时间限制的同步、可以被中断的同步
    原理 monitor是JVM的一个同步工具,synchronized还通过内存指令屏障来保证共享变量的可见性。 使用AQS在代码级别实现,通过Unsafe.park调用操作系统内核进行阻塞。
    功能 非公平锁、要么随机唤醒一个线程要么唤醒全部线程 ReentrantLock:可指定公平锁/非公平锁。提供Condition(条件)类,可实现分组唤醒。提供中断等待机制【lockInterruptibly()】

    使用总结:

    写同步的时候,优先考虑synchronized,如果有特殊需要,再进一步优化。ReentrantLock和Atomic如果用的不好,不仅不能提高性能,还可能带来灾难。

    • sync是关键字属于JVM层面 Lock是具体类是api层面的锁
    • sync不需要用户手动释放锁执行完成后自动释放对锁的占用,ReentrantLock则需要用户手动释放,否则会出现死锁
    • sync不可中断,除非抛出异常或者正常运行完成,ReentrantLock可中断
    • sync非公平锁,ReentrantLock两者皆可
    • 绑定多个条件condition
      • sync没有
      • ReentrantLock用来实现分组唤醒需要唤醒的线程们,可以精确唤醒,而不像sync要么随机唤醒,要么全部唤醒。

5、volatile(可见性,有序性)

  1. 在主内存和工作内存交互时,直接与主内存产生交互【不通过缓存】,进行读写操作,保证数据的内存可见性【实时刷新】;

    • 修改volatile变量时JVM会向处理器发送一条lock前缀的指令,会强制将修改后的值刷新的主内存中。
    • 修改volatile变量后会导致其他线程工作内存中对应的变量值失效。因此,再读取该变量值的时候就需要重新从读取主内存中的值。
  2. 禁止 JVM 进行的指令重排序。

    • 内存屏障(memory barriers)
      • 阻止屏障两侧的指令重排序
      • 强制刷新主内存数据,以及让缓存中相应的数据失效
    • happens-before:它是判断数据是否存在竞争、线程是否安全的主要依据,保证了多线程环境下的可见性
      • 程序顺序原则:一个线程内保证语义的串行性.对于单线程来讲,必须保证重排后的结果与重排前一致。
      • volatile规则:volatile变量的写,先发生于后续对这个变量的读.这保证了volatile变量的可见性.
      • 监视锁规则:对于一个锁的解锁,先发生于随后对这个锁的加锁. 否则随后的加锁将会失败.
      • 传递性:A先于B,B等于C,那么A必然先于C.
      • 线程启动规则:Thread对象的start()方法先发生于此线程的其他任意动作。
      • 线程终止规则:线程的所有操作都先发生于对此线程的终止检测,可以通过Thread.join()方法结束、Thread.isAlive()的返回值等手段检测到线程已经终止执行。
      • 线程中断规则:对线程interrupt()方法的调用先发生于被中断线程的代码检测到中断时事件的操作。
      • 对象终结规则:一个对象的初始化完成(构造函数执行结束)先发生于它的finalize()方法的开始

Synchronized vs Volatile

  - **作用:** volatile解决的是变量在多线程间的可见性,而syn解决的是多线程间访问资源的同步性- **修饰域:** volatile只能修饰变量;synchronized可以修饰方法和代码块- **原子性:** volatile保证数据可见性,但不保证原子性;而syn可以保证原子性,也可以间接保证可见性,因为会将私有内存和公共内存中的数据做同步- **性能:** volatile是线程同步的轻量级实现,性能优于synchronized,但synchronized的性能不断被优化提升,实际上表现不差

6、CAS

整个AQS同步组件,atomic原子类操作都是基于CAS实现

可重入锁(递归锁)

可重入锁又名递归锁,是指同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。对于Java ReentrantLock而言, 其名字是Reentrant Lock即是重新进入锁。对于synchronized而言,也是一个可重入锁。可重入锁的一个好处是可一定程度避免死锁。线程可以进入任何一个它已经拥有的锁同步着的代码块

加锁时通过CAS算法,将对象放在一个双向链表中,每次获得锁时候,看下当前维护的那个线程id和请求的线程id是否一致

自旋锁

尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,

好处减少线程上下文切换的消耗,缺点是循环会消耗CPU

独占锁(写锁)/共享锁(读锁)

ReentrantReadWriteLock

  • 独占锁也叫排他锁,是指该锁一次只能被一个线程所持有。如果线程T对数据A加上排它锁后,则其他线程不能再对A加任何类型的锁。获得排它锁的线程即能读数据又能修改数据。JDK中的synchronized和JUC中Lock的实现类就是互斥锁。
  • 共享锁是指该锁可被多个线程所持有。如果线程T对数据A加上共享锁后,则其他线程只能对A再加共享锁,不能加排它锁。获得共享锁的线程只能读数据,不能修改数据。

乐观锁/悲观锁

悲观锁认为自己在使用数据的时候一定有别的线程来修改数据,因此在获取数据的时候会先加锁,确保数据不会被别的线程修改。Java中,synchronized关键字和Lock的实现类都是悲观锁。

而乐观锁认为自己在使用数据时不会有别的线程修改数据,所以不会添加锁,只是在更新数据的时候去判断之前有没有别的线程更新了这个数据。如果这个数据没有被更新,当前线程将自己修改的数据成功写入。如果数据已经被其他线程更新,则根据不同的实现方式执行不同的操作(例如报错或者自动重试)。

从上面的描述我们可以看出,悲观锁适合写操作非常多的场景,乐观锁适合读操作非常多的场景,不加锁会带来大量的性能提升。悲观锁在Java中的使用,就是利用各种锁。乐观锁在Java中的使用,是无锁编程,常常采用的是CAS算法,典型的例子就是原子类,通过CAS自旋实现原子操作的更新。

6、并发工具

1、CountDownLatch

  • 计数器闭锁:

​ 以计数器形式来处理需要等待的线程数,可用来让一个线程来等待其他多个线程完成任务后再执行,比如让主线程来计算其他子线程运行时的耗时。

  • 构造器:

    public CountDownLatch(int count)

    count:需要等待的线程数,当count减到0时才会执行。

  • 重要方法:

    await():等待count指定的线程线程数都完成后再执行。

    await(long timeout, TimeUnit unit):等待一段时间,不管其他线程玩不完成都执行。

    countDown():让等待的线程数-1,当一个线程完成任务后调用。

public class TestCountDownLatch {public static void main(String[] args) {/*** CountDownLatch闭锁的执行原理: latch.countDown(); 即每有一个线程完成工作后,* CountDownLatch= CountDownLatch - 1; 当 CountDownLatch  0时,表示每有其他线程在执行了*/final CountDownLatch latch = new CountDownLatch(10);LatchDemo ld = new LatchDemo(latch);long start = System.currentTimeMillis();for (int i = 0; i < 10; i++) {new Thread(ld).start();}try {latch.await();  //让 main 线程执行到此处时,进行闭锁,等待其他线程完成操作后再执行后续代码。} catch (InterruptedException e) {e.printStackTrace();}long end = System.currentTimeMillis();// 不用闭锁时,11个线程(1个主线程,10个子线程)同时执行,是无法计算耗时的。System.out.println("耗时为(ms):" + (end - start));}
}class LatchDemo implements Runnable {private CountDownLatch latch;// 闭锁public LatchDemo(CountDownLatch latch) {this.latch = latch;}@Overridepublic void run() {//保证线程安全synchronized (this) {try {// 打印 5W 以内的奇数for (int i = 0; i < 50000; i++) {if ((i & 1)  1) {System.out.println(i);}}} finally {// latch.countDown();即CountDownLatch = CountDownLatch - 1;使用闭锁时要保证该代码一定执行到。latch.countDown();}}}
}

2、CyclicBarrier

  • 回环栅栏:

​ 通过它可以实现让一组线程相互等待至某个状态(barrier)之后再全部同时执行。

  • 构造器:

public CyclicBarrier(int parties)

public CyclicBarrier(int parties, Runnable barrierAction);

parties:让多少个线程或者任务等待至barrier状态。

barrierAction:所有线程/任务都到达barrier状态后,需要执行的附加任务。【让最后一个完成任务的线程去执行

  • 重要方法:

await():让当前线程等待其他线程都处于barrier状态后再执行。

await(long timeout, TimeUnit unit):等待到指定时间,若还有线程未到barrier状态,直接让到达barrier的线程执行后续任务。

public class TestCyclicBarrier {public static void main(String[] args) {int N = 4;CyclicBarrier barrier = new CyclicBarrier(N, new Runnable() {@Overridepublic void run() {System.out.println("当前执行额外任务的线程" + Thread.currentThread().getName());}});for (int i = 0; i < N; i++)new Writer(barrier).start();}static class Writer extends Thread {private CyclicBarrier cyclicBarrier;public Writer(CyclicBarrier cyclicBarrier) {this.cyclicBarrier = cyclicBarrier;}@Overridepublic void run() {System.out.println("线程" + Thread.currentThread().getName() + "正在写入数据...");try {Thread.sleep(5000); // 以睡眠来模拟写入数据操作System.out.println("线程" + Thread.currentThread().getName() + "写入数据完毕,等待其他线程写入完毕");cyclicBarrier.await();} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"所有线程写入完毕,继续处理其他任务...");}}
}

3、Semaphore

  • 信号量

    可以控制同时访问的线程个数,通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。

  • 构造器

    Semaphore(int permits);

    public Semaphore(int permits, boolean fair)

    permits:表示许可数目,即同时可以允许多少线程进行访问。

    fair:表示是否是公平的,公平即等待时间越久的越先获取许可。

  • 重要方法

    availablePermits()

    ​ 获取可用的许可数目。

    acquire()【阻塞】:

    ​ 获取一个许可。若无许可能够获得,则会一直等待,直到获得许可。

    acquire(int permits)【阻塞】:

    ​ 获取permits个许可。

    release()【阻塞】:

    ​ 释放一个许可。不要求在释放许可之前必须先获获得许可,但如果没有获取许可,就直接release许可会导致Semaphore允许的同时线程数+1(即便将Semaphore设置成final也会+1)。

    release(int permits)【阻塞】:

    ​ 释放permits个许可。

    boolean tryAcquire()【非阻塞】:

    ​ 尝试获取一个许可,若获取成功,则立即返回true,若获取失败,则立即返回false。

    boolean tryAcquire(long timeout, TimeUnit unit)【非阻塞,需要等待 timeout 时间】:

    ​ 尝试获取一个许可,若在指定的时间内获取成功,则立即返回true,否则则立即返回false。

    tryAcquire(int permits)【非阻塞】:

    ​ 尝试获取permits个许可,若获取成功,则立即返回true,若获取失败,则立即返回false。

    boolean tryAcquire(int permits, long timeout, TimeUnit unit)【非阻塞,需要等待 timeout 时间】:

    ​ 尝试获取permits个许可,若在指定的时间内获取成功,则立即返回true,否则则立即返回false

4、区别

工具 作用 可否重用
CountDownLatch 用于某个线程等待若干个其他线程执行完任务之后,它才执行 不可
CyclicBarrier 用于一组线程互相等待至某个状态,然后这一组线程再同时执行 可以
Semaphore 可以控制同时访问的线程个数,它一般用于控制对某组资源的访问权限。 /

二、线程池

1、优点

  1. 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
  2. 提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
  3. 提高线程的可管理性。线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控。

2、线程池体系结构

1、线程池的体系结构:
|--java.util.concurrent.Executor://负责线程的使用与调度的根接口|--**ExecutorService	//子接口:线程池的主要接口。|--ThreadPoolExecutor	//线程池的实现类,只有线程池的使用功能,无法进行延迟等任务。|--ScheduledExecutorService	//子接口,继承了ExecutorService:负责线程的调度。|--ScheduledThreadPoolExecutor //继承了ThreadPoolExecutor类,实现ScheduledExecutorService接口,提供线程池的使用与调度功能。2、工具类:ExecutorsExecutorService newCachedThreadPool();//创建缓存线程池,线程的数量无限制,会根据需求自动更改数量。ExecutorService newFixedThreadPool(int number);//创建固定大小的线程池ExecutorService newSingleThreadExecutor();//创建单个线程池。线程池中只有一个线程。ScheduledThreadPoolExecutor newScheduledThreadPool(); //创建固定大小的线程池,还可以延迟或定时的执行任务。

3、线程池的核心参数ThreadPoolExecutor

  • corePoolSize:核心线程数量,线程池中常驻的线程数量。
  • maximumPoolSize:线程池允许的最大线程数,非核心线程在超时之后会被清除,受限于CAPACITY
  • workQueue:任务阻塞队列,用于存储等待执行的任务。
  • keepAliveTime:线程没有任务执行时可以保持的时间【非核心线程】。
  • unit:时间单位
  • threadFactory:线程工厂,用来创建线程。
  • rejectHandler:当任务队列已满时,拒绝任务提交时的策略:
    • AbortPolicy【默认】:丢掉任务,并抛RejectedExecutionException异常。
    • DiscardPolicy:直接丢掉任务,不抛异常。
    • DiscardOldestPolicy:丢掉最老的任务,然后调用execute立刻执行该任务(新进来的任务)。
    • CallerRunsPolicy【推荐】:在调用者的当前线程去执行这个任务。

线程池的最大容量CAPACITY中的前三位用作标志位,也就是说工作线程的最大容量为(2^29)-1

4、线程池四种模型【Executors提供】

  • newCachedThreadPool:创建一个可缓存的线程池,如果线程池的当前规模超过了处理需求时,那么将回收空闲的线程,当需求增加时,则可以添加新的线程,线程池的规模不存在任何的限制。
  • newFixedThreadPool:创建一个固定大小的线程池,提交一个任务时就创建一个线程,直到达到线程池的最大数量,这时线程池的大小将不再变化。
  • newSingleThreadPool:创建一个单线程的线程池,它只有一个工作线程来执行任务,可以确保按照任务在队列中的顺序来串行执行,如果这个线程异常结束将创建一个新的线程来执行任务。
  • newScheduledThreadPool:创建一个固定大小的线程池,并且以延迟或者定时的方式来执行任务,类似于Timer。

4、线程池创建线程的核心逻辑

在创建了线程池后,等待提交过来的任务请求

  1. 当调用execute()方法添加一个任务请求,线程池会做如下判断:
    • 如果正在运行的线程数小于corePoolSize,那么马上会创建线程运行这个任务
    • 如果正在运行的线程数大于或者等于corePoolSize,那么会将这个任务放入队列
    • 如果这时候队列满了并且正在运行的线程数量还小于maximumPoolSize,那么还是要创建非核心线程运行这个任务
    • 如果队列满了并且线程数大于或者等于maximumPoolSize,那么会启动饱和拒绝策略来执行
  2. 当一个线程完成时,它会从队列中取下一个任务来执行
  3. 当一个线程无事可做,且超过一定的时间(keepAliveTime)时,线程池会判断:
    • 如果当前运行的线程数大于corePoolSize,那么这个线程会停掉
    • 所以线程池的所有任务完成后,它最终会收缩到corePoolSize的大小

5、队列阻塞策略

  • 直接提交(如:SynchronousQueue)。

    ​ 工作队列的默认选项是 SynchronousQueue,它将任务直接提交给线程而不保持它们。在此,如果不存在可用于立即运行任务的线程,则试图把任务加入队列将失败,因此会构造一个新的线程。此策略可以避免在处理可能具有内部依赖性的请求集时出现锁。直接提交通常要求无界maximumPoolSizes
    以避免拒绝新提交的任务。当命令以超过队列所能处理的平均数连续到达时,此策略允许无界线程具有增长的可能性。

  • 无界队列(如:LinkedBlockingQueue)。

    ​ 使用无界队列(如不具有预定义容量的 LinkedBlockingQueue)将导致在所有 corePoolSize
    线程都忙时新任务在队列中等待。这样,创建的线程就不会超过 corePoolSize。(因此,maximumPoolSize
    的值也就无效了。)当每个任务完全独立于其他任务,即任务执行互不影响时,适合于使用无界队列 。

  • 有界队列(如 ArrayBlockingQueue)。

    ​ 使用有限的 maximumPoolSizes 时,有界队列有助于防止资源耗尽,但是可能较难调整和控制。队列大小和最大池大小可能需要相互折衷:使用大型队列和小型池可以最大限度地降低 CPU 使用率、操作系统资源和上下文切换开销,但是可能导致人工降低吞吐量。如果任务频繁阻塞(例如,如果它们是 I/O 边界),则系统可能为超过您许可的更多线程安排时间。使用小型队列通常要求较大的池大小,CPU使用率较高,但是可能遇到不可接受的调度开销,这样也会降低吞吐量。

三、死锁

多个线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力干涉将无法推动下去,如果系统资源充足,进程的资源请求都会得到满足,死锁出现的可能性很低,否则会因争夺资源而陷入死锁

1、原因

  • 系统资源不足
  • 进程运行推进顺序不合适
  • 资源分配不当

2、解决

​ Java Visual VM 图形化监控工具

  1. jps定位进程号
  2. jstack找到死锁查看
  3. jconsole可视化工具分析

四、ThreadLocal

1、解决问题(解决数据库连接、Session管理)

  • 并发问题:使用 ThreadLocal 代替 Synchronized 来保证线程安全,同步机制采用空间换时间 -> 仅仅先提供一份变量,各个线程轮流访问,ThreadLocal 每个线程都持有一份变量,访问时互不影响。

  • 数据存储问题: ThreadLocal 为变量在每个线程中创建了一个副本,所以每个线程可以访问自己内部的副本变量。

2、底层实现

  1. 每个Thread维护着一个ThreadLocalMap的引用

  2. ThreadLocalMap是ThreadLocal的内部类,用Entry来进行存储

  3. 调用ThreadLocal的set()方法时,实际上就是往ThreadLocalMap设置值,key是ThreadLocal对象,值是传递进来的对象

  4. 调用ThreadLocal的get()方法时,实际上就是往ThreadLocalMap获取值,key是ThreadLocal对象

  5. ThreadLocal本身并不存储值,它只是作为一个key来让线程从ThreadLocalMap获取value。

    ThreadLocalMap的实现原理跟HashMap 差不多,内部有一个 Entry 数组,一个 Entry通常至少包括key,value , 特殊的是这个Entry继承了 WeakReference 也就是说它是弱引用的所以可能会有 内存泄露 的情况。ThreadLocal 负责管理 ThreadLocalMap ,包括插入,删除 等等

jdk8优化原因:

  1. 这样设计之后每个Map存储的Entry数量就会变小,因为之前存储数量是由Thread的数量决定的,现在是由 ThreadLocal 的数量决定的
  2. Thread销毁之后,对应的ThreadLocalMap也会随之销毁,减少内存的占用

3、内部类ThreadLocalMap

核心方法

  • getEntry(ThreadLocal<?> key)
  • set(ThreadLocal> key, Object value)`

ThreadLocalMap的set()则是采用开放定址法,开放定址法就是不会有链式的结构,如果冲突了,以当前位置为基准再找一个判断,直到找到一个空的地址。set()操作除了存储元素外,还有一个很重要的作用,就是replaceStaleEntry()和cleanSomeSlots(),这两个方法可以清除掉key == null 的实例,防止内存泄漏。
get()方法有一个重要的地方当key == null时,调用了expungeStaleEntry()方法,该方法用于处理key == null,有利于GC回收,能够有效地避免内存泄漏。

4、线程之间如何传递 ThreadLocal 对象

Threadlocal 的子类 InheritableThreadLocal

5、ThreadLocalsynchronized的区别?

synchronized关键字采用了以“时间换空间”的方式,提供一份变量,让不同的线程排队访问。而ThreadLocal采用了“以空间换时间”的方式,为每一个线程都提供一份变量的副本,从而实现同时访问而互不影响。

https://www.jianshu.com/p/e200e96a41a0

6、ThreadLocal为什么会内存泄漏

ThreadLocalMap的key为ThreadLocal实例,他是一个弱引用,我们知道弱引用有利于GC的回收,当key == null时,GC就会回收这部分空间,但value不一定能被回收,因为他和Current Thread之间还存在一个强引用的关系。由于这个强引用的关系,会导致value无法回收,如果线程对象不消除这个强引用的关系,就可能会出现内存泄漏。有些时候,我们调用ThreadLocalMap的remove()方法进行显式处理。

7、java常用的线程调度算法

抢占式,一个线程用完CPU之后,操作系统会根据线程优先级和线程饥饿情况等数据算出一个总的优先级并分配下一个时间片给某个线程执行

8、单例模式的线程安全性

  • 概念:负责创建自己的对象,同时确保只有单个对象被创建

  • 饿汉式:线程安全

  • 懒汉式:线程不安全

  • 双检锁:线程安全

9、为什么spring单例是线程安全

  • ThreadLocal
  • 单例:无状态的Bean(⽆状态就是一次操作,不能保存数据。无状态对象(Stateless Bean),就是没有实例变量的对象,不能保存数据,是不变类,是线程安全的。)适合⽤用不变模式,技术就是单例模式,这样可以共享实例,提高性能。
查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 第10课 Altium Designer20(AD20)+VESC6.4实战教程:绘制原理图7(北冥有鱼)

    第10课 Altium Designer20(AD20)+VESC6.4实战教程:绘制原理图7(北冥有鱼)...

    2024/4/24 14:49:41
  2. 【XXE漏洞】笔记

    XXE漏洞:xml外部实体注入漏洞 XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件,造成文件读取,命令执行,内网端口扫描,攻击内网网站,发起dos攻击等危害。...

    2024/4/26 10:29:29
  3. cpufreq 使用记录

    文章目录1. 引子2. CPU 频率相关调节2.1 CPU 频率2.1.1 频率概念理解2.1.2 HW支持2.1.2.1 DVFS2.1.2.2 CPU hotplug2.1.2.3 thermal 采集2.2 如何查看当前系统的Frequence2.2.1 cpuinfo driver2.2.2 如何人为加大负载2.2.3 如何查看负载2.3 系统提供的调节CPU Frequence方案2.3…...

    2024/5/5 18:01:17
  4. ajax的介绍与使用方法

    ajax的介绍与使用方法一、 ajax的工作原理1、什么是ajax?2、ajax所包含的技术?3、ajax的原理?4、xhr取得响应?二、 原生ajax的使用方法1、ajax请求的五个步骤2、ajax-get方式请求案例3、ajax-post方式请求案例三、 jqery 中的ajax使用方法四、 ajax的优缺点 一、 ajax的工作…...

    2024/4/20 17:50:27
  5. Hive的元数据库从derby迁移到MySQL

    Hive的元数据库从derby到MySQL 1.安装hive ​ (1)解压tar包 ​ (2)修改hive-env.sh ​ 修改HADOOP_HOME和 ​ HIVE_CONF_DIR 2.替换默認derby数据库为mysql ​ (1)先查询卸载原有的mysql数据库 ​ rpm -qa|grep mysql ​ sudo rpm -e --nodeps mysql-libs-5.1.73-7.e…...

    2024/5/3 20:22:13
  6. 往数据库表里面插入或者更新大量数据(我奶奶都能看懂)

    一、背景现在有个演示的项目,需要导入100家的单位信息进入数据库。当然,你如果是计算机专业或者相关从业人员,实现这个需求很简单,但是如果是会计专业的或者其他专业的,他们不懂,你怎么教他操作呢?不可能从SQL教到编程吧?下面跟我一起操作。二、第一种方法,直接用exec…...

    2024/5/3 21:33:22
  7. 文件IO

    一、标准IO操作 man 1 系统命令 man 2 系统调用 man 3 库函数 标准IO:c库提供的一组函数接口,具有缓存机制,提高编程效率。围绕着流(FILE*)来进行操作。 FILE *fp; //FILE是在stdio.h中定义的结构体类型,封装了与文件有关的信息,如文件句柄、位置指针及缓冲区等,缓冲文件…...

    2024/4/18 21:30:44
  8. RolarWAN协议

    参考资料:http://murata.eetrend.com/node/10020601 end node节点的认证或者叫激活,有两种模式1)OTTA2)ABP2 报文格式PHY MAC FHDR Fctrl Fopts MACCommand3 三种终端类型class A:class B:在支持CLassA类型的接收方式之外,还需周期性监测网络下行的ping slot,…...

    2024/4/24 14:49:38
  9. Linux应急响应基础(Linux服务器入侵响应)学习

    主要是阶段性的总结一些Linux下的应急响应常用命令及技巧 文章目录登录和终端信息查看登录用户信息查看登录失败信息查看用户上一次的登录情况查看当前登录系统的情况查看登录成功信息查看登录失败信息强制用户下线终端历史命令用户信息查看是否有新增用户查看是否有特权用户查…...

    2024/4/24 14:49:37
  10. 一天的 React 入门 总结

    前面的话 这是一篇算React入门级的文章,初次接触React,有问题请指出~~~。 安装方式 这里介绍搭建一个 react 项目的两种方式: CDN链接 和 官方推荐的 create-react-app 脚手架 CDN 链接 创建一个 index.html 文件,将 React、React DOM、Babel 这三个 CDN 链接引入到 hea…...

    2024/4/24 14:49:37
  11. 蓝桥杯 BFS经典题 —— 卡片换位(单走华容道)

    BFS 经典题,可能答案不是最优的,参考一下也是可以的 ^ _ ^题目: 你玩过华容道的游戏吗? 这是个类似的,但更简单的游戏。 看下面 3 x 2 的格子 +---+---+---+ | A | * | * | +---+---+---+ | B | | * | +---+---+---+ 在其中放5张牌,其中A代表关羽,B代表张飞, * 代表士…...

    2024/4/24 14:49:35
  12. MQTT协议研究

    MQTT协议是轻量级的以太网数据交换协议,在物联网中应用越来越广泛,本文简要介绍MQTT协议的相关知识点。1. MQTT协议简介:MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。在很多情况下,包括受…...

    2024/4/24 14:49:35
  13. c++ 迭代器访问二维数组

    #include<iostream> #include<vector>int main(){std::vector<int> arr(5); // 创建一维数组for(int i=0;i<5;++i)std::cout << arr[i]<<" ";std::cout << std::endl;std::cout << std::endl;std::vector<int> …...

    2024/4/24 14:49:33
  14. 【教程】每天30分钟免费的视频自动生成字幕的方法

    0.问题经常要剪视频,有时候自己讲的希望能加个字幕,但是网上基本都是收费的,而且对于我这种做视频没什么收入的UP主来说有点贵了。所以一直在寻找一个便捷一点的或者说省钱一点的方法。但是手机上发现有个软件效果还不错,每天免费30分钟:显示是会员有30分钟,会员就是注册…...

    2024/4/24 14:49:36
  15. leetcode#栈#1441. 用栈操作构建数组

    给你一个目标数组 target 和一个整数 n。每次迭代,需要从 list = {1,2,3…, n} 中依序读取一个数字。 请使用下述操作来构建目标数组 target : Push:从 list 中读取一个新元素, 并将其推入数组中。 Pop:删除数组中的最后一个元素。 如果目标数组构建完成,就停止读取更多…...

    2024/4/24 14:49:34
  16. Vue.js火速上手第十六章——混合 mixins

    一、在main.js中定义两个全局组件定义一个tooltip组件,鼠标移入显示h1,鼠标移除h1消失。定义一个button组件,点击按钮显示h1,再点击按钮h1消失。Vue.component(tooltip,{template:`<div><span @mouseenter="show" @mouseout="hide">鼠标提…...

    2024/4/24 14:49:31
  17. CTF密码学题目初探(二)

    CTF密码学题目初探(二)密码学总结(一)1.换位加密2.替换加密 密码学总结(一) 在上一篇文章里写了12种常见的编码,这一篇文章主要总结换位加密和替换加密。 1.换位加密栅栏密码(Rail-fence Cipher) 在线栅栏密码解密链接 栅栏密码(Rail-fence Cipher)就是把要加密的明文分…...

    2024/4/24 14:49:29
  18. 我需要弄清楚,一个飞控装到不同的机架之后,需要调整什么,如何调试。

    我需要弄清楚,一个飞控装到不同的机架之后,需要调整什么,如何调试。不管是pixhawk还是匿名无名,我觉得这是我应该基本掌握的,不难总是买别人拼装好的机架。这应该是一个很基本的要求。。...

    2024/4/24 14:49:29
  19. Mysql事务概述和使用规范

    事务概述在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。事务用来管理DDL、DML、DCL操作,比如 insert,update,delete 语句,默认是自动提交的。 一般来说,事务是必…...

    2024/4/24 14:49:28
  20. MATLAB的H5文件操作

    忙活了一晚,终于弄明白了MATLAB的h5文件生成的步骤,下面来说一说。 首先,我们需要创建h5文件: savepath =D:/pycharm/train.h5; #请使用绝对路径,相对路径不好用 h5create(savepath, /data1, [1 size_input size_input count]);这里我们创建了一个数据集,名字叫data,注意…...

    2024/4/20 8:16:02

最新文章

  1. 【C++】命名空间和IO流

    一切都从这个代码开始&#xff01;&#xff01;&#xff01; #include<iostream>using namespace std;int main() {cout << "Hello world!" << endl;return 0; } 命名空间 当我们写了这么一段代码的时候... Ctrl F5运行&#xff0c;发现报错了..…...

    2024/5/8 14:57:14
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/5/7 10:36:02
  3. 如何转行成为产品经理?

    转行NPDP也是很合适的一条发展路径&#xff0c;之后从事新产品开发相关工作~ 一、什么是NPDP&#xff1f; NPDP 是产品经理国际资格认证&#xff0c;美国产品开发与管理协会&#xff08;PDMA&#xff09;发起的&#xff0c;是目前国际公认的唯一的新产品开发专业认证&#xff…...

    2024/5/4 23:56:47
  4. 腾讯云轻量服务器流量不够用了会怎么样?

    腾讯云轻量应用服务器是限制月流量的&#xff0c;如果当月流量不够用了&#xff0c;流量超额了怎么办&#xff1f;流量超额后&#xff0c;需要另外支付流量费&#xff0c;如果你的腾讯云账号余额&#xff0c;就会自动扣除对应的流量费&#xff0c;如果余额不足&#xff0c;轻量…...

    2024/5/8 8:45:36
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/8 6:01:22
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/5/7 9:45:25
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/5/4 23:54:56
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/7 14:25:14
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/5/4 23:54:56
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/5/4 23:55:05
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/5/4 23:54:56
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/5/7 11:36:39
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/5/4 23:54:56
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/5/6 1:40:42
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/5/4 23:54:56
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/5/4 23:55:17
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/5/7 9:26:26
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/5/4 23:54:56
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/4 23:55:06
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/5/5 8:13:33
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/5/4 23:55:16
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/5/4 23:54:58
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/6 21:42:42
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/5/4 23:54:56
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; 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
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在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