
06 并发多线程
文章平均质量分 79
多线程
喵了个咪的回忆丶
Java后台
展开
-
面试:Volatile、Synchronized、ReentrantLock、CAS
Volatilevolatile 关键字可以保证可见性,以及防止指令重排序。原理:它会将修改的值立即写入主内存,并使其他线程的工作内存里对应的这个数据失效,这些线程想再次读取这个数据时就重新去主内存中读取。Synchronized可以保证原子性、可见性、有序性。原理: 使用了两个监控指令 enter 和 exit。enter 指令指向代码块开始位置,执行它时线程会尝试获取锁,计数器...原创 2020-04-21 13:07:04 · 428 阅读 · 0 评论 -
线程的生命周期和状态(6种)
线程的生命周期和状态(6种) 线程创建后会处于新建状态,调用 start() 方法后处于可运行状态,可运行状态的线程获得CPU时间片后就处于 Runnable 运行状态。当线程执行 wait() 方法后进入 WAITING 等待状态,而 TIME_WAITING 超时等待状态相当于在等待状态的基础上增加了超时限制,比如通过 sleep 或 wait 方法可以将线程置于超时等待状态。当超时时...原创 2019-11-28 14:47:48 · 456 阅读 · 1 评论 -
面试题——ThreadLocal
1.ThreadLocal是什么?每个线程内部都有一个由ThreadLocal维护的ThreadLocalMap,它类似于HashMap。在ThreadLocalMap中,会初始化一个大小为16的Entry数组,用来保存每一个key-value键值对,其中key是一个弱引用,也是ThreadLocal对象本身,而 value 存的是线程变量的值。当创建一个ThreadLocal变量时,每个访问它...原创 2019-08-27 20:56:04 · 628 阅读 · 2 评论 -
创建线程的四种方式
1.线程与进程进程是代码在数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位。线程是进程的一个执行路径,一个进程中至少有一个线程,进程中的多个线程共享进程的堆和方法区资源,但是每个线程有自己的程序计数器和栈区域。线程是CPU资源分配的基本单位。程序计数器是一块内存区域,用来记录线程当前要执行的指令地址,它是线程私有的,因为线程是占用CPU执行的基本单位,而CPU一般是使用时间片...原创 2019-06-23 13:45:11 · 513 阅读 · 0 评论 -
面试题——线程池
1.为什么要用线程池创建线程和回收线程都会占用系统资源,如果任务来了才创建线程那么响应时间会变长。提前创建一些线程并交给线程池管理,可以降低资源消耗、提高响应速度、提高线程的可管理性。2. 线程池执行流程(原理)如果当前运行的线程少于corePoolSize,则创建新线程来执行任务,这一步骤需要获取全局锁。如果运行的线程等于或多于corePoolSize,则将任务加入BlockingQu...原创 2019-09-04 18:19:10 · 5408 阅读 · 1 评论 -
n个线程顺序打印0到100数
public class n个线程打印0到100 { static int result = 0; public static void main(String[] args) throws InterruptedException { //假设有20个线程 int n = 20; Thread[] threads = new Thread[n]; //创建n个信号量 final Semaphore[] s .原创 2020-09-28 15:08:48 · 749 阅读 · 0 评论 -
三个线程交叉打印0-100之间的数
三个线程交叉打印0-100之间的数import java.util.concurrent.atomic.AtomicInteger;public class 三个线程交替打印0到100 { public static void main(String[] args) { final AtomicInteger i = new AtomicInteger(0); final int n = 100; Thread t1 = new Thread(原创 2020-09-28 14:22:32 · 433 阅读 · 0 评论 -
两个线程分别打印0到100之间的奇偶
两个线程分别打印0到100之间的奇偶public class 两个线程分别打印0到100之间的奇偶 { private static final Object LOCK = new Object(); private static int i = 0; private static final int TOTAL = 100; public static void main(String[] args) { Thread thread1 = new Thr原创 2020-09-28 14:12:52 · 179 阅读 · 0 评论 -
什么是线程安全
什么是线程安全在多线程环境下也不会出现数据不一致就叫线程安全。如何保证线程安全互斥同步(synchronized 和 ReentrantLock)非阻塞同步(CAS)原创 2020-09-11 11:49:40 · 104 阅读 · 0 评论 -
互斥锁和自旋锁
互斥锁互斥锁:指的是同一时刻只能有一个线程获得互斥锁,其余试图请求该互斥锁的线程将会被挂起,不占用CPU资源,直到前面的线程释放了该互斥锁,其余线程才会被唤醒。它只有两种状态:上锁和解锁。可以用来控制对共享资源的访问。自旋锁自旋锁:当某个线程获得自旋锁后,别的线程会一直做循环,尝试加锁。也就是它们并不会让出CPU,这样做的好处是节省了线程从睡眠状态到唤醒状态过程中内核产生的消耗,在加锁时间短暂的环境下这点会提高很大的效率。所以自旋锁适用于锁的持有者保存时间较短的情况。自旋锁有可能造成死锁,比原创 2020-09-01 14:08:42 · 178 阅读 · 0 评论 -
悲观锁和乐观锁
悲观锁总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。悲观锁适用于读少写多的场景。行锁、表锁、读锁、写锁都是悲观锁,还有 synchronized 和 ReentrantLock 等独占锁也是悲观锁思想的实现。乐观锁总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新时会判...原创 2019-11-28 20:30:47 · 106 阅读 · 0 评论 -
公平锁和非公平锁
公平锁指的是先等待的线程先获得锁,能够减少饥饿发生的概率,因为等待越久的请求越优先满足。非公平锁指的是无视队列顺序直接抢锁,可能导致某些线程一直拿不到锁,造成线程饥饿。具体流程是:公平锁在进行 lock 时,首先会进行 tryAcquire 操作判断等待队列中是否有其他线程在等待,如果有,则 tryAcquire 失败,然后进入等待队列。而非公平锁在进行 lock 时,首先会直接通...原创 2019-12-06 21:40:02 · 210 阅读 · 0 评论 -
读写锁,共享锁,排它锁
什么是读写锁(ReentrantReadWriteLock)?读写锁与排他锁的区别?读写锁维护了一对锁,一个读锁和一个写锁,读锁是一个共享锁,写锁是一个排他锁,在读操作时获取读锁。写操作时获取写锁。当写锁被获取到时,后续其他线程的读写操作都会被阻塞,写锁释放之后,所有操作继续执行。当读锁被获取到时,后续的读操作不会被阻塞,其他线程的写操作会被阻塞,读写锁相比一般的排他锁性能有了很大提升。读...原创 2019-08-28 16:58:48 · 1105 阅读 · 0 评论 -
1000个线程进行 +1 操作(AtomicInteger、CountDownLatch)
1000个线程进行 +1 操作,如何保证线程安全得到正确的1000?import java.util.concurrent.CountDownLatch;import java.util.concurrent.atomic.AtomicInteger;public class 线程2 { static AtomicInteger count = new AtomicInteger(0); static CountDownLatch cdl = new CountDownLatch(1原创 2020-08-14 16:47:06 · 1150 阅读 · 0 评论 -
如何让线程顺序执行?
如何让线程顺序执行?使用线程的 join 方法:join 是 Thread 的方法,它的作用是 调用线程 需要等待 join 线程执行完成后,才能继续往下执行。使用线程的 wait 方法:wait 是 Object 类的方法,它的作用是让当前线程进入等待状态,同时wait也会让当前线程释放它持有的锁,当其他线程调用此对象的 notify 方法或 notifyAll 方法时,当前线程被唤醒进入就绪状态。notify 和 notifyAll 方法也是 Object 类的方法,作用是唤醒当前对象上的等待线程原创 2020-08-12 17:45:17 · 450 阅读 · 0 评论 -
execute 和 submit 的区别
execute 方法和 submit 方法的区别?(如何向线程池提交任务)execute 方法没有返回值,所以无法判断任务是否被线程池执行成功。submit 方法有返回值,返回一个Future类型的对象,通过这个Future对象可以判断任务是否执行成功。...原创 2020-08-09 14:27:47 · 257 阅读 · 0 评论 -
CompletableFuture、EasyExcel、PageInfo
CompletableFutureCompletableFuture 是 Java8 提出的一个支持非阻塞的多功能Future。它提供了一个异步运算结果的建模,让我们把耗时的操作从我们本身的调用线程中释放出来,只需要完成后进行回调即可,就好像我们去饭店吃饭,不需要我们自己去煮饭,我们点餐后就可以继续干自己的事,然后餐厅煮好了就回调我开始吃饭。通过引入CompletableFuture......原创 2020-07-27 16:10:41 · 622 阅读 · 0 评论 -
AtomicInteger原理
AtomicInteger原理 AtomicInteger 利用 CAS 、volatile 和本地方法来保证原子操作。它有两个重要的参数,一个是 Volatile 修饰的 value,表示AtomicInteger对象当前的实际取值;一个是long类型的 valueOffSet,表示value字段在AtomicInteger对象中的偏移量。CAS原理是拿期望值和原来的值做对比,如果相同就更新...原创 2019-11-30 16:00:56 · 2023 阅读 · 0 评论 -
面试题——线程池常用的阻塞队列?手写生产者消费者模式?
1. 阻塞队列ArrayBlockingQueue:由数组结构组成的有界阻塞队列,按照先进先出的原则。LinkedBlockingQueue:由链表结构组成的有界阻塞队列,按照先进先出的原则。PriorityBlockingQueue:支持优先级排序的无界阻塞队列。SynchronousQueue:不存储元素的阻塞队列,来一个处理一个。详细理解ArrayBlockingQueue与L...原创 2019-08-30 15:03:37 · 450 阅读 · 0 评论 -
Executor 框架
面试题——说下 Executor?一. Executor 框架的结构(三大部分)Executor 框架主要由三大部分组成:任务(Runnable / Callable):包括被执行任务需要实现的 Runnable 接口或 Callable 接口。任务的执行。包括任务执行机制的核心接口 Executor 和继承 Executor 的 ExecutorService 接口。异步计算的结果。...原创 2019-12-06 18:01:28 · 150 阅读 · 0 评论 -
线程间的通信方式
线程间的通信方式一. volatile 和 Synchronized二. wait 和 notify 方法实现的等待/通知机制三. Thread.join 方法,线程等待前面的线程终止后才能从等待中返回,也是一种等待/通知机制。四. ThreadLocal,线程可以根据一个 ThreadLocal 对象查询到绑定在这个线程上的值。五. 管道输入和输出流,用于线程间的数据传输,传输媒介为内...原创 2019-12-05 22:16:55 · 142 阅读 · 0 评论 -
线程同步的方式、同步和互斥
线程同步的互斥的区别互斥是指线程的共享资源同时只允许一个访问者对它进行访问,具有独占性,但无法限制访问的顺序,也就是访问是无序的。同步是指在互斥的基础上,通过xx机制实现访问者对资源的有序访问,也就是说线程通过同步建立了执行顺序的关系。线程同步的方式信号量:它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目在用CreateSemaphore()创建信号量时即要同时指出允许的最大资源计数和当前可用资源计数。一般是将当前可用资源计数设置为最 大资源计数,每增加一个原创 2020-08-01 18:54:36 · 323 阅读 · 0 评论 -
JDK1.6的锁优化(偏向所,轻量级锁,自旋锁,锁消除,锁粗化)
JDK1.6 对锁的实现引入了大量的优化,如偏向锁、轻量级锁、自旋锁、适应性自旋锁、锁消除、锁粗化等技术来减少锁操作的开销。偏向锁它的意思是会偏向于第一个获得它的线程,如果在接下来的执行中,该锁没有被其他线程获取,那么持有偏向锁的线程就不需要进行同步。这样在没有多线程竞争的情况下,减少了传统重量级锁使用操作系统互斥量产生的性能消耗。偏向锁失败的话会先升级为轻量级锁。轻量级锁轻量级锁提升同步...原创 2019-11-29 16:29:24 · 583 阅读 · 0 评论 -
start方法和run方法的区别?为什么调用的要是start方法
为什么我们调用 start() 方法时会执行 run() 方法,为什么我们不能直接调用 run() 方法? new 一个线程后,线程进入了新建状态,调用 start() 方法,会启动一个线程并使线程进入就绪状态,当分配到时间片后就可以开始运行了,然后自动执行 run() 方法的内容,这是真正的多线程工作。 而直接执行 run() 方法,会把 run 方法当成 main 线程下的一个普通方法去执...原创 2019-11-28 18:04:14 · 384 阅读 · 0 评论 -
sleep() 、wait() 、yield() 区别和共同点? notify 方法 、 join 方法
sleep() 方法和 wait() 方法的区别和共同点?sleep 方法没有释放锁,而 wait 方法释放了锁 。wait() 方法被调用后,线程不会自动苏醒,需要别的线程调用同一个对象上的 notify() 或 notifyAll() 方法。sleep() 方法执行完成后,线程会自动苏醒。sleep() 方法sleep 方法是 Thread 类的静态方法,线程用它来控制自身的流程...原创 2019-11-28 16:28:20 · 226 阅读 · 0 评论 -
线程中断;interrupted 和 isInterrupted 的区别
1. interrupted和isInterrupted的区别public class s { public static void main(String[] args) throws InterruptedException { Thread threadOne = new Thread(new Runnable() { @Override ...原创 2019-06-27 21:06:35 · 956 阅读 · 1 评论 -
JMM
1. JMM原子性是指一个操作不可以被中断可见性是指一个线程修改了某一个共享变量的值时,其他线程能立即知道这个修改。有序性:程序执行时可能进行指令重排,重排后的指令与原指令的顺序未必一致2. volatilevolatile不能保证原子性volatile可以保证可见性,当一个线程修改了volatile修饰变量的值时,该值会被写入主内存,而其他CPU的缓存区中存储的该变量的值也会因...原创 2019-08-18 12:50:37 · 176 阅读 · 0 评论 -
面试题——如何减少上下文切换?
无锁并发编程。多线程竞争锁时,会引起上下文切换,所以多线程处理数据时,可以尽量减少锁的竞争或避免使用锁,比如将数据的ID按照Hash算法取模分段,不同的线程处理不同段的数据。CAS算法。Java的(Atomic)原子包使用CAS算法来更新数据,不需要加锁。使用最少的线程。避免创建不需要的线程,比如任务很少,但是创建了很多线程来处理,这样会造成大量线程都处于等待状态。协程:在单线程里实现多任...原创 2019-08-26 15:06:09 · 526 阅读 · 0 评论 -
面试题——happens-before 规则
happens-before 规则一个线程内保证语义的串行性volatile变量的写先于读发生锁规则:解锁必然发生在加锁前A先于B,B先于C,那么A必然先于C线程的 start() 方法先于它的每一个动作线程的所有操作先于线程的终结线程的中断先于被中断线程的代码构造函数的执行、结束 先于 finalize() 方法...原创 2019-08-27 14:00:11 · 312 阅读 · 0 评论 -
面试题——AQS
AQS抽象同步队列简称AQS,它是一个先进先出的双向队列。AQS内部有一个CLH队列,用来记录所有等待锁的线程。AQS还拥有一个内部类ConditionObject,它是条件变量,每个条件变量的内部都维护了一个条件队列,当一个线程调用条件变量的await方法时,该线程会释放它持有的锁,并被转换为Node节点插入到条件变量对应的条件队列里,同时还会唤醒CLH队列里的一个线程获取到被释放的锁。而si...原创 2019-09-04 13:19:23 · 4576 阅读 · 1 评论 -
面试题—— CountDownLatch、CyclicBarrier、Semaphore
1. CountDownLatchCountDownLatch允许一个或多个线程等待其他线程完成操作。它的构造函数接收一个int类型的参数count作为计数器,当调用CountDownLatch的countDown方法时,计数器count的值就会减一,这个减一操作是通过CAS完成的,当计数器为0时程序才会向下执行。还有一个await()方法,可以使线程阻塞,当计数器为0时,阻塞队列的线程才会被唤...原创 2019-09-04 12:19:22 · 785 阅读 · 0 评论 -
面试题——多线程算法题
1. 代码实现控制三个线程打印出ABCABC…ABC(10次);两个线程,一个线程打印A,一个线程打印B,如何实现两个线程按顺序打印出ABABAB…?2. 多线程打印奇偶数3. 线程1先打印1,2,3,4,5,线程2打印6,7,8,9,10,线程3打印11,12,13,14,15。接着再由线程1打印16,17,18,19,20,以此类推,知道打印到754. a = [1,2,3,4]; b ...原创 2019-09-18 13:46:18 · 879 阅读 · 1 评论 -
非面试:volatile
关键字volatile1.多线程的三个特性?原子性:指一个操作不可中断。即使是多个线程一起执行时,一个操作一旦开始,就不会被其他线程干扰。可见性:是指当一个线程修改了某一个共享变量的值,其他线程能够立即知道这个修改。有序性:在并发时,程序的执行可能会出现乱序。有序性问题的原因是程序在执行时,可能会进行指令重排,重排后的指令与原指令的顺序未必一致。2.产生线程可见性的原因?保证线程可见...原创 2019-08-26 14:07:16 · 205 阅读 · 0 评论 -
手写 Volatile 、Synchronized 、线程池的使用场景
import java.util.concurrent.ExecutorService;import static java.util.concurrent.Executors.newFixedThreadPool;public class Test { private static volatile int i = 0; //加 volatile 没用,它并不能保证原子性 ...原创 2019-12-14 21:44:01 · 160 阅读 · 0 评论