在JUC并发编程01中说到了,什么是JUC、线程和进程、Lock锁、生产者和消费者问题、8锁现象、集合类不安全、Callable(简单)、常用辅助类、读写锁
https://blog.csdn.net/qq_45441466/article/details/117197861

10、阻塞队列


阻塞队列:BlockingDeque



什么情况下我们会使用阻塞队列:
多线程并发处理,线程池!

学会使用队列
添加、移除

四组API

方式 抛出异常 由返回值 阻塞等待 超时等待
添加 add offer() put() offer(“d”, 2,TimeUnit.SECONDS)
移除 remove poll() take() poll(2,TimeUnit.SECONDS)
判断队列首 element peek()
package com.panghl.juc.bq;import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;/*** @Author panghl* @Date 2021/6/1 19:28* @Description BlockQueue**/
public class Test {public static void main(String[] args) throws InterruptedException {//        test1();
//        test2();
//        test3();test4();}/*** 抛出异常*/public static void test1(){//队列的大小ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);System.out.println(blockingQueue.add("A"));System.out.println(blockingQueue.add("B"));System.out.println(blockingQueue.add("C"));//IllegalStateException: Queue full 抛出异常!//System.out.println(blockingQueue.add("d"));System.out.println(blockingQueue.remove());System.out.println(blockingQueue.remove());System.out.println(blockingQueue.remove());//java.util.NoSuchElementException 抛出异常
//        System.out.println(blockingQueue.remove());System.out.println(blockingQueue.peek());//检测队首元素System.out.println(blockingQueue.element());//查看队首元素是谁}/*** 有返回值*/public static void test2(){BlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);System.out.println(blockingQueue.offer("A"));System.out.println(blockingQueue.offer("B"));System.out.println(blockingQueue.offer("C"));System.out.println(blockingQueue.offer("d")); //false 不抛出异常!System.out.println(blockingQueue.element());//查看队首元素是谁System.out.println(blockingQueue.poll());System.out.println(blockingQueue.poll());System.out.println(blockingQueue.poll());System.out.println(blockingQueue.poll());System.out.println(blockingQueue.peek());//检测队首元素System.out.println(blockingQueue.element());//查看队首元素是谁}/*** 等待,阻塞(一直阻塞)*/public static void test3() throws InterruptedException {BlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);//一直阻塞blockingQueue.put("a");blockingQueue.put("b");blockingQueue.put("c");blockingQueue.put("d"); //队列没有位置了,一直阻塞System.out.println(blockingQueue.take());System.out.println(blockingQueue.take());System.out.println(blockingQueue.take());System.out.println(blockingQueue.take()); //没有这个元素,一直阻塞}/*** 超时等待*/public static void test4() throws InterruptedException {BlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);//一直阻塞blockingQueue.offer("a");blockingQueue.offer("b");blockingQueue.offer("c");
//        blockingQueue.offer("d", 2,TimeUnit.SECONDS); //2s 后无位置,超时退出blockingQueue.poll();blockingQueue.poll();blockingQueue.poll();blockingQueue.poll(2,TimeUnit.SECONDS);//等待超过2s就退出}
}

同步队列

没有容量,进去一个元素,必须等待取出来之后,才能往里面放一个元素!
put、take

package com.panghl.juc.bq;import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;/*** @Author panghl* @Date 2021/6/1 20:21* @Description 同步队列* 和其他的BlockingQueue 不一样,SynchronousQueue 不存储元素* put了一个元素,必须从里面先take取出来,否则不能再put进去值!**/
public class SyncQueueDemo {public static void main(String[] args) {//同步队列BlockingQueue<String> syncQueue = new SynchronousQueue<>();new Thread(() -> {try {System.out.println(Thread.currentThread().getName() + "put 1");syncQueue.put("1");System.out.println(Thread.currentThread().getName() + "put 2");syncQueue.put("2");System.out.println(Thread.currentThread().getName() + "put 3");syncQueue.put("3");} catch (InterruptedException e) {e.printStackTrace();}}, "T1").start();new Thread(() -> {try {TimeUnit.SECONDS.sleep(2);System.out.println(Thread.currentThread().getName() + "take 1");syncQueue.take();TimeUnit.SECONDS.sleep(2);System.out.println(Thread.currentThread().getName() + "take 2");syncQueue.take();TimeUnit.SECONDS.sleep(2);System.out.println(Thread.currentThread().getName() + "take 3");syncQueue.take();} catch (InterruptedException e) {e.printStackTrace();}}, "T2").start();}
}

11、线程池(重点)

池化技术:程序的运行,本质:占用系统的资源!优化资源的使用!事先准备好一些资源,有人要用,就来我这里拿,用完之后还给我。

线程池的好处
1、降低资源的消耗
2、提高响应的速度
3、方便管理

线程复用,可以控制最大并发数、管理线程

线程池:三大方法

package com.panghl.juc.pool;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** @Author panghl* @Date 2021/6/1 20:37* @Description 工具类 :3大方法* 使用了线程池之后,使用线程池来创建线程**/
public class Demo01 {public static void main(String[] args) {//        ExecutorService threadPool = Executors.newSingleThreadExecutor();//单个线程
//        ExecutorService threadPool = Executors.newFixedThreadPool(5); //创建一个固定的线程池的大小ExecutorService threadPool = Executors.newCachedThreadPool(); //可伸缩的,遇强则强,遇弱则弱try {for (int i = 0; i < 10; i++) {threadPool.execute(() -> {System.out.println(Thread.currentThread().getName() + "ok");});}} catch (Exception e) {e.printStackTrace();} finally {//线程池用完,程序结束,关闭线程池threadPool.shutdown();}}
}

7大参数

    public static ExecutorService newSingleThreadExecutor() {return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()));}public static ExecutorService newFixedThreadPool(int nThreads) {return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());}public static ExecutorService newCachedThreadPool() {return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());}//本质:ThreadPoolExecutor()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.acc = System.getSecurityManager() == null ?null :AccessController.getContext();this.corePoolSize = corePoolSize;this.maximumPoolSize = maximumPoolSize;this.workQueue = workQueue;this.keepAliveTime = unit.toNanos(keepAliveTime);this.threadFactory = threadFactory;this.handler = handler;}

手动创建一个线程池

四种拒绝策略

package com.panghl.juc.pool;import java.util.concurrent.*;/*** @Author panghl* @Date 2021/6/1 20:37* @Description 工具类 :4种拒绝策略
new ThreadPoolExecutor.AbortPolicy() //银行满了,还有人进来,不处理这个人的,抛出异常
new ThreadPoolExecutor.CallerRunsPolicy() //哪来的去哪里! main线程执行
new ThreadPoolExecutor.DiscardPolicy() //队列满了,丢掉任务,不会抛出异常!
new ThreadPoolExecutor.DiscardOldestPolicy() //队列满了,尝试去和最早的竞争,也不会抛出异常!**/
public class Demo02 {public static void main(String[] args) {// 自定义线程池!工作 ThreadPoolExecutorExecutorService threadPool = new ThreadPoolExecutor(2,5,3,TimeUnit.SECONDS,new LinkedBlockingQueue<>(3),Executors.defaultThreadFactory(),new ThreadPoolExecutor.DiscardOldestPolicy() //队列满了,尝试去和最早的竞争,也不会抛出异常!);try {//最大承载:Deque + max//超过 RejectedExecutionExceptionfor (int i = 1; i <=9; i++) {threadPool.execute(() -> {System.out.println(Thread.currentThread().getName() + "ok");});}} catch (Exception e) {e.printStackTrace();} finally {//线程池用完,程序结束,关闭线程池threadPool.shutdown();}}
}

new ThreadPoolExecutor.AbortPolicy() //银行满了,还有人进来,不处理这个人的,抛出异常 new
ThreadPoolExecutor.CallerRunsPolicy() //哪来的去哪里! main线程执行 new
ThreadPoolExecutor.DiscardPolicy() //队列满了,丢掉任务,不会抛出异常! new
ThreadPoolExecutor.DiscardOldestPolicy() //队列满了,尝试去和最早的竞争,也不会抛出异常!

小结和扩展
最大线程到底该如何定义?
1、CPU 密集型 ; 几核,就是几,可以保持CPU的效率最高!
2、IO 密集型 ; 判断你程序中十分耗IO的线程。
程序 15个大型任务 io十分占用资源!

package com.panghl.juc.pool;import java.util.concurrent.*;/*** @Author panghl* @Date 2021/6/1 20:37* @Description 工具类 :4种拒绝策略
new ThreadPoolExecutor.AbortPolicy() //银行满了,还有人进来,不处理这个人的,抛出异常
new ThreadPoolExecutor.CallerRunsPolicy() //哪来的去哪里! main线程执行
new ThreadPoolExecutor.DiscardPolicy() //队列满了,丢掉任务,不会抛出异常!
new ThreadPoolExecutor.DiscardOldestPolicy() //队列满了,尝试去和最早的竞争,也不会抛出异常!**/
public class Demo02 {public static void main(String[] args) {// 自定义线程池!工作 ThreadPoolExecutor//最大线程到底该如何定义?//1、CPU  密集型 ; 几核,就是几,可以保持CPU的效率最高!//2、IO   密集型 ; 判断你程序中十分耗IO的线程。//      程序  15个大型任务  io十分占用资源!//获取CPU的核数System.out.println(Runtime.getRuntime().availableProcessors());ExecutorService threadPool = new ThreadPoolExecutor(2,Runtime.getRuntime().availableProcessors(),3,TimeUnit.SECONDS,new LinkedBlockingQueue<>(3),Executors.defaultThreadFactory(),new ThreadPoolExecutor.DiscardOldestPolicy() //队列满了,尝试去和最早的竞争,也不会抛出异常!);try {//最大承载:Deque + max//超过 RejectedExecutionExceptionfor (int i = 1; i <=9; i++) {threadPool.execute(() -> {System.out.println(Thread.currentThread().getName() + "ok");});}} catch (Exception e) {e.printStackTrace();} finally {//线程池用完,程序结束,关闭线程池threadPool.shutdown();}}
}

12、四大函数式接口(必须掌握)

@FunctionalInterface
public interface Runnable {public abstract void run();
}
//超级多FunctionalInterface
//简化编程模型,在新版本的框架底层大量应用!
//foreach (消费者类的函数式接口)


代码测试:

Function函数式接口

package com.panghl.juc.function;import java.util.function.Function;/*** @Author panghl* @Date 2021/6/1 21:32* @Description Function 函数式接口,有一个输入参数,有一个输出* 只要是函数式接口可以用lambda表达式简化**/
public class Demo01 {public static void main(String[] args) {//工具类:输出输入的值
//        Function<String, String> function = new Function<String, String>() {//            @Override
//            public String apply(String o) {//                return o;
//            }
//        };Function<String, String> function = (str)->{return str;};System.out.println(function.apply("1"));}
}

断定型接口

package com.panghl.juc.function;import java.util.function.Predicate;/*** @Author panghl* @Date 2021/6/1 21:40* @Description 断定性接口:有一个输入参数,返回值只能是 布尔值!**/
public class Demo2 {public static void main(String[] args) {//判断字符串是否为null
//        Predicate<String> predicate = new Predicate<String>() {//            @Override
//            public boolean test(String o) {//                return o.isEmpty();
//            }
//        };Predicate<String> predicate = (str)->{return str.isEmpty();};System.out.println(predicate.test("1"));}
}

Consumer 消费型接口

package com.panghl.juc.function;import java.util.function.Consumer;/*** @Author panghl* @Date 2021/6/1 21:48* @Description Consumer 消费型接口:只有输入,没有返回值**/
public class Demo03 {public static void main(String[] args) {//        Consumer<String> consumer = new Consumer<String>() {//            @Override
//            public void accept(String str) {//                System.out.println(str);
//            }
//        };Consumer<String> consumer = (str) -> {System.out.println(str);};consumer.accept("helo");}
}

Supplier 供给型接口

package com.panghl.juc.function;import java.util.function.Supplier;/*** @Author panghl* @Date 2021/6/1 21:50* @Description Supplier 供给型接口,没有参数,只有返回值**/
public class Demo04 {public static void main(String[] args) {//        Supplier<String> supplier = new Supplier<String>() {//            @Override
//            public String get() {//                return "helo";
//            }
//        };Supplier<String> supplier = ()->{return "adhelo";};System.out.println(supplier.get());}
}

13、Stream流式计算

package com.panghl.juc.stream;import java.util.Arrays;
import java.util.List;/*** @Author panghl* @Date 2021/6/1 21:58* @Description 题目要求:一分钟内完成此题,只能用一行代码实现!* 1、ID必须是偶数* 2、年龄必须大于23岁* 3、用户名转为大写字母* 4、用户名字母倒着排序* 5、只输出一个用户!**/
public class Test {public static void main(String[] args) {User u1 = new User(1, "a", 21);User u2 = new User(2, "b", 22);User u3 = new User(3, "c", 23);User u4 = new User(4, "d", 24);User u5 = new User(5, "e", 25);List<User> users = Arrays.asList(u1, u2, u3, u4, u5);users.stream().filter((u) -> {return u.getId() % 2 == 0;}).filter((u)->{return u.getAge()>23;}).map((u)->{return u.getName().toUpperCase();}).sorted((o1,o2)->{return o1.compareTo(o2);}).limit(1).forEach(System.out::println);}
}

14、ForkJoin

什么是ForkJoin
ForkJoin在JDK1.7,并执行任务!提高效率。大数据量!
大数据:Map Reduce(把大任务拆分为小任务)

ForkJoin特点:工作窃取
这个里面维护的都是双端队列

ForkJoin

package com.panghl.juc.forkjoin;import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;/*** @Author panghl* @Date 2021/6/2 22:30* @Description 求和计算的任务!* 3000 6000(ForkJoin) 9000(Stream并行流)* 如何使用forkjoin ?* 1、forkjoinPool 通过它来执行* 2、计算任务 forkjoinPool.execute(ForkJoinTask task)* 3、要继承ForkJoinTask**/
public class ForkJoinDemo extends RecursiveTask<Long> {private Long start; //1private Long end;  //1990900000//临界值private Long temp = 10000L;public ForkJoinDemo(Long start, Long end) {this.start = start;this.end = end;}@Overrideprotected Long compute() {if ((end - start) > temp) {//分支合并计算Long sum = 0L;for (Long i = start; i < end; i++) {sum += i;}System.out.println(sum);return sum;} else { //forkjoinlong middle = (start + end) / 2; //中间值ForkJoinDemo forkJoinDemo1 = new ForkJoinDemo(start, middle);forkJoinDemo1.fork(); //拆分任务,把任务压入线程队列ForkJoinDemo forkJoinDemo2 = new ForkJoinDemo(middle + 1, end);forkJoinDemo2.fork();return forkJoinDemo1.join() + forkJoinDemo2.join();}}}
package com.panghl.juc.forkjoin;import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;/*** @Author panghl* @Date 2021/6/2 22:45* @Description TODO**/
public class Test {public static void main(String[] args) throws ExecutionException, InterruptedException {test3();}public static void test1(){Long sum = 0L;long start = System.currentTimeMillis();for (Long i = 1L; i < 10_0000_000; i++) {sum+=i;}long end = System.currentTimeMillis();System.out.println("sum="+"时间:"+(end-start));}//会使用ForkJoinpublic static void test2() throws ExecutionException, InterruptedException {long start = System.currentTimeMillis();ForkJoinPool forkJoinPool = new ForkJoinPool();ForkJoinDemo forkJoinDemo = new ForkJoinDemo(0L,10_0000_000L);ForkJoinTask<Long> forkJoinTask = forkJoinPool.submit(forkJoinDemo);Long aLong = forkJoinTask.get();long end = System.currentTimeMillis();System.out.println("sum="+aLong+"时间:"+(end-start));}//Stream并行流public static void test3(){long start = System.currentTimeMillis();long reduce = LongStream.rangeClosed(0L, 10_0000_000L).parallel().reduce(0, Long::sum);long end = System.currentTimeMillis();System.out.println("sum="+reduce+"时间:"+(end-start));}
}

15、异步回调

package com.panghl.juc.future;import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;/*** @Author panghl* @Date 2021/6/2 23:02* @Description 异步调用: Ajax* 异步执行  成功回调**/
public class Demo01 {public static void main(String[] args) throws ExecutionException, InterruptedException {//发送一个请求--》没有返回值的runAsync 异步回调
//        CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(()->{//            try {//                TimeUnit.SECONDS.sleep(2);
//            } catch (InterruptedException e) {//                e.printStackTrace();
//            }
//            System.out.println(Thread.currentThread().getName()+"休眠结束===>runSync=>Void");
//        });
//        System.out.println("1111");
//        completableFuture.get(); //获取阻塞执行结果//有返回值的 supplyAsync 异步回调//ajax,成功和失败的回调//返回的是错误信息;CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(()->{int i = 1/0;System.out.println(Thread.currentThread().getName()+"休眠结束===>runSync=>Integer");return 1024;});completableFuture.whenComplete((t,u)->{System.out.println("t=>"+t); //正常的返回结果System.out.println("u=>"+u); //错误信息:java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero}).exceptionally((e)->{System.out.println(e.getMessage());return 233; //可以获取到错误的返回结果});Integer integer = completableFuture.get();System.out.println(integer);}
}

16、JMM

Volatile是Java虚拟机提供轻量级的同步机制
1、保证可见性
2、不保证原子性
3、禁止指令重排

什么是JMM?
JMM:Java内存模型,不存在的东西,概念!约定!

关于JMM的一些同步的约定:
1、线程解锁前,必须把共享变量立刻刷回主存。
2、线程加锁前,必须读取主存中的最新值到工作内存中!
3、加锁和解锁是同一把锁

线程 工作内存主内存
8中操作:


问题:程序不知道主内存的值被修改了。

package com.panghl.juc.volatil;import java.util.concurrent.TimeUnit;/*** @Author panghl* @Date 2021/6/2 23:36* @Description**/
public class JMMDemo {private static  int num = 0;public static void main(String[] args) throws InterruptedException {new Thread(() -> {//线程1while (num == 0) {}}).start();TimeUnit.SECONDS.sleep(2);num = 1;System.out.println(num);}}

18.Volatile

1、保证了可见性

package com.panghl.juc.volatil;import java.util.concurrent.TimeUnit;/*** @Author panghl* @Date 2021/6/2 23:36* @Description**/
public class JMMDemo {private static volatile int num = 0;public static void main(String[] args) throws InterruptedException {new Thread(() -> {//线程1while (num == 0) {}}).start();TimeUnit.SECONDS.sleep(2);num = 1;System.out.println(num);}}

2、不保证原子性
原子性:不可分割
线程A在执行任务的时候,不能被打扰,也不能被分割。要么同时成功,要嘛同时失败。

package com.panghl.juc.volatil;/*** @Author panghl* @Date 2021/6/2 23:44* @Description 不保证原子性**/
public class VDemo02 {private volatile static int num = 0;private static void add(){num++;}public static void main(String[] args) {for (int i = 0; i < 20; i++) {new Thread(()->{for (int i1 = 0; i1 < 1000; i1++) {add();}}).start();}while (Thread.activeCount()>2){//main gc 默认执行Thread.yield();}System.out.println(Thread.currentThread().getName()+"==>num:"+num);}
}


如果不加lock和synchronized,怎么样保证原子性?

使用原子类,解决原子性问题

package com.panghl.juc.volatil;import java.util.concurrent.atomic.AtomicInteger;/*** @Author panghl* @Date 2021/6/2 23:44* @Description 不保证原子性**/
public class VDemo02 {//原子类的 Integerprivate volatile static AtomicInteger num = new AtomicInteger();private static void add(){//        num++; //你是一个原子性操作num.getAndIncrement(); //AtomicInteger+1 的方法, CAS}public static void main(String[] args) {for (int i = 0; i < 20; i++) {new Thread(()->{for (int i1 = 0; i1 < 1000; i1++) {add();}}).start();}while (Thread.activeCount()>2){//main gc 默认执行Thread.yield();}System.out.println(Thread.currentThread().getName()+"==>num:"+num);}
}

这些类的底层都直接和操作系统挂钩!在内存中修改值!Unsafe类是一个很特殊的存在!

3、指令重排
什么是指令重排:你写的程序,计算机并不是按照你写的那样去执行的。
源代码–》编译器优化的重排–》指令并行也可能会重排–》内存系统也会重排–》执行

处理器在进行指令重排的时候,考虑:数据之间的依赖性!

int x =1; //1
int y = 2; //2
x=x+5; //3
y=x*x; //4
我们所期望的:1234 结果2134 1324

可能造成影响的结果: ab xy 这四个值默认都是0;

线程A 线程B
x=a y=b
b=1 a=2

正常的结果:x=0;y=0 ;但是可能由于指令重排

线程A 线程B
b=1 a=2
x=a y=b

指令重排导致的诡异结果:x=2;y=1;

volatile 可以避免指令重排
内存屏障。CPU指令。作用:
1、保证特定的操作的执行顺序!
2、可以保证某些变量的内存可见性(利用这些特性volatile实现了可见性)

volatile是可以保证可见性。不能保证原子性,由于内存屏障,可以保证避免指令重排的现象产生!

20、深入理解CAS

什么是CAS
大厂必须要深入研究底层!有所突破!修内功,操作系统,计算机网络原理

Unsafe类




CAS: 比较当前工作内存中的值和主内存的值,如果这个值是期望的,那么执行操作!如果不是就一直循环。

缺点:
1、循环会耗时
2、一次性只能保证一个共享变量的原子性
3、ABA问题

CAS:ABA问题(狸猫换太子)

package com.panghl.juc.cas;import java.util.concurrent.atomic.AtomicInteger;/*** @Author panghl* @Date 2021/6/3 21:33* @Description TODO**/
public class CASDemo {//CAS compareAndSet: 比较并交换!public static void main(String[] args) {AtomicInteger atomicInteger = new AtomicInteger(2020);// 期望、更新// public final boolean compareAndSet(int expect, int update)//如果我期望的值达到了,name就更新,否则,就不更新,CAS 是CPU的并发原语atomicInteger.compareAndSet(2020,2021);System.out.println(atomicInteger.get());// ===============捣乱的线程============System.out.println(atomicInteger.compareAndSet(2020,2021));System.out.println(atomicInteger.get());System.out.println(atomicInteger.compareAndSet(2021,2020));System.out.println(atomicInteger.get());// ===============期望的线程============System.out.println(atomicInteger.compareAndSet(2020,6666));System.out.println(atomicInteger.get());}
}

21、原子引用

解决ABA问题,引入原子引用!对应的思想:乐观锁
带版本号的原子操作。
注意

package com.panghl.juc.cas;import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;/*** @Author panghl* @Date 2021/6/3 21:33* @Description TODO**/
public class CASDemo {//CAS compareAndSet: 比较并交换!public static void main(String[] args) {//        AtomicInteger atomicInteger = new AtomicInteger(2020);//int Integer 注意,如果泛型是一个包装类,注意对象的引用问题!!!//正常在业务操作,这里面比较的都是一个个对象AtomicStampedReference<Integer> atomicReference = new AtomicStampedReference<>(1,1);// 乐观锁的原理相同!!!new Thread(()->{int stamp = atomicReference.getStamp(); //获取版本号System.out.println("A1->"+stamp);try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(atomicReference.compareAndSet(1, 2, atomicReference.getStamp(), atomicReference.getStamp() + 1));System.out.println("A2->"+atomicReference.getStamp());System.out.println(atomicReference.compareAndSet(2, 1, atomicReference.getStamp(), atomicReference.getStamp() + 1));System.out.println("A2->"+atomicReference.getStamp());},"A").start();new Thread(()->{int stamp = atomicReference.getStamp(); //获取版本号System.out.println("B1->"+stamp);try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(atomicReference.compareAndSet(1, 3, stamp, stamp + 1));System.out.println("B2->"+atomicReference.getStamp());},"B").start();}
}

21、各种锁的理解

1、公平锁、非公平锁
公平锁:非常公平,不能够插队,必须先来后到!
非公平锁:非常不公平,可以插队(默认非公平锁)

2、可重入锁
可重入锁(递归锁)

Synchronized版本

package com.panghl.juc.lock;/*** @Author panghl* @Date 2021/6/3 22:16* @Description Synchronized**/
public class Demo01 {public static void main(String[] args) {Phone phone = new Phone();new Thread(()->{phone.sms();},"A").start();new Thread(()->{phone.sms();},"B").start();}
}class Phone{public synchronized void sms(){System.out.println(Thread.currentThread().getName()+"sms");call(); //这里也有锁}public synchronized void call(){System.out.println("打电话");}
}

Lock版本

package com.panghl.juc.lock;import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*** @Author panghl* @Date 2021/6/3 22:19* @Description Lock**/
public class Demo02 {public static void main(String[] args) {Phone2 phone = new Phone2();new Thread(() -> {phone.sms();}, "A").start();new Thread(() -> {phone.sms();}, "B").start();}
}class Phone2 {Lock lock = new ReentrantLock();public void sms() {lock.lock();// lock 锁必须配对,否则就会死在里面lock.lock();try {System.out.println(Thread.currentThread().getName() + "sms");call(); //这里也有锁} catch (Exception e) {e.getMessage();} finally {lock.unlock();lock.unlock();}}public void call() {lock.lock();try {System.out.println(Thread.currentThread().getName() +"打电话");} catch (Exception e) {e.getMessage();} finally {lock.unlock();}}
}

3、自旋锁

自定义锁测试:

package com.panghl.juc.lock;import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;/*** @Author panghl* @Date 2021/6/3 22:26* @Description 自旋锁**/
public class SpinlockDemo {// int 0// Thread nullAtomicReference<Thread> atomicReference = new AtomicReference<>();//加锁public void myLock(){Thread thread = Thread.currentThread();System.out.println(thread.getName()+"==>lock");// 自旋锁while (!atomicReference.compareAndSet(null,thread)){System.out.println("自旋中....");}}//解锁public void myUnLock(){Thread thread = Thread.currentThread();System.out.println(thread.getName()+"==>myUnlock");atomicReference.compareAndSet(thread,null);}}
package com.panghl.juc.lock;import java.util.concurrent.TimeUnit;/*** @Author panghl* @Date 2021/6/3 22:30* @Description**/
public class TestSpinLock {public static void main(String[] args) {//底层使用的自旋锁CASSpinlockDemo spinlockDemo = new SpinlockDemo();new Thread(()->{spinlockDemo.myLock();try {TimeUnit.SECONDS.sleep(3);}catch (Exception e){e.getMessage();}finally {spinlockDemo.myUnLock();}},"A1").start();new Thread(()->{spinlockDemo.myLock();try {TimeUnit.SECONDS.sleep(1);}catch (Exception e){e.getMessage();}finally {spinlockDemo.myUnLock();}},"A2").start();}
}

4、死锁

死锁测试,怎么排除死锁:

package com.panghl.juc.lock;import java.util.concurrent.TimeUnit;/*** @Author panghl* @Date 2021/6/3 22:37* @Description 死锁**/
public class DeadLockDemo {public static void main(String[] args) {String lockA="lockA";String lockB="lockB";new Thread(new MyThread(lockA,lockB),"A1").start();new Thread(new MyThread(lockB,lockA),"A2").start();}
}class MyThread implements Runnable{private String lockA;private String lockB;public MyThread(String lockA, String lockB) {this.lockA = lockA;this.lockB = lockB;}@Overridepublic void run() {synchronized (lockA){System.out.println(Thread.currentThread().getName()+"lock:"+lockA+"=>get"+lockB);try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}synchronized (lockB){System.out.println(Thread.currentThread().getName()+"lock:"+lockB+"=>get"+lockA);}}}
}

解决问题
1、使用 jps -l 定位进程号

2、使用 jstack 进程号 找到死锁问题

多线程进阶=》JUC并发编程02相关推荐

  1. JUC并发编程02——AQS源码剖析

    1.AQS介绍 相信每个Java Coder 都使用过或者至少听说过AQS, 它是抽象队列同步器AbstractQueuedSynchronizer 的简称,在juc包下.它提供了一套可用于实现锁同步 ...

  2. 【尚硅谷】大厂必备技术之JUC并发编程——笔记总结

    [JUC并发编程01]JUC概述 关键字:进程和线程.进程和线程.wait和sleep.并发与并行.管程.用户线程和守护线程 [JUC并发编程02]Lock接口 关键字:synchronized.Lo ...

  3. 多线程进阶=》JUC并发编程

    多线程进阶=>JUC并发编程 1.什么是JUC ​ JUC是java.util.concurrent的简写. ​ 用中文概括一下,JUC的意思就是java并发编程工具包. ​ 并发编程的本质就是 ...

  4. 基于《狂神说Java》JUC并发编程--学习笔记

    前言: 本笔记仅做学习与复习使用,不存在刻意抄袭. -------------------------------------------------------------------------- ...

  5. JUC并发编程(java util concurrent)(哔站 狂神说java juc并发编程 摘录笔记)

    JUC并发编程(java util concurrent) 1.什么是JUC JUC并不是一个很神秘的东西(就是 java.util 工具包.包.分类) 业务:普通的线程代码 Thread Runna ...

  6. 爬梯:JUC并发编程(三)

    学习资源整理自:B站<狂神说> 书接上回 JUC并发编程 12.CompletableFuture 异步回调 理解 父类:Future,对将来的某个事件的结果进行建模 可以用ajax进行理 ...

  7. ❤️《JUC并发编程从入门到高级》(建议收藏)❤️

    JUC并发编程 1.什么是JUC JUC的意思就是java并发编程工具包,与JUC相关的有三个包:java.util.concurrent.java.util.concurrent.atomic.ja ...

  8. Java JUC并发编程详解

    Java JUC并发编程详解 1. JUC概述 1.1 JUC简介 1.2 进程与线程 1.2 并发与并行 1.3 用户线程和守护线程 2. Lock接口 2.1 Synchronized 2.2 什 ...

  9. JUC并发编程小总结

    JUC是Java编发编程中使用的工具类,全称为java.util.concurrent.近期在大厂面试中屡屡被问到关于JUC的相关知识点问题,其重要性不言而喻,学好用好JUC可以说是每一个Java程序 ...

最新文章

  1. 区块链教程Fabric1.0源代码分析Peer peer channel命令及子命令实现
  2. 互联网公司IT系统架构进化之路
  3. AD在Windows Server 2003中的更新(中)
  4. 第八节:详细讲解Java中的异常处理情况与I/O流的介绍以及类集合框架
  5. 困了。还得背课文。变词型
  6. java 桥接模式_JAVA设计模式之【桥接模式】
  7. 用java进行LDAP用户登陆(用户认证)及修改密码
  8. VMware 修复 Workstation、Fusion 中多个严重的代码执行漏洞
  9. python三本经典书籍-《python编程入门经典》python之父推荐这三本书让你更快入门...
  10. notification 是同步的
  11. 关于添加文件删除权限
  12. 城市数字孪生解决方案
  13. 构建AD域 、 管理AD域
  14. ssh命令行使用明文密码连接远程服务器并执行命令
  15. 无心剑中译莎士比亚诗20首
  16. tab按钮样式 vue_vant 解决tab切换插件标题样式自定义的问题
  17. 9. Go复合类型-数组
  18. 数据库操作的异常Cannot perform this operation because the connection pool has been close
  19. STM32F103C8T6基础开发教程(HAL库)—开发环境配置
  20. Circum Triangle(圆上三角形)

热门文章

  1. 机器学习中参数模型和非参数模型理解
  2. 表情识别(二)--基于CNN分类
  3. Socket TCP协议解决粘包、半包问题的三种解决方案
  4. 温习Android基础知识——《第一行代码(第三版)》读书笔记 Chapter 2 Kotlin语法
  5. 嵌入式系统导论(彭蔓蔓等·人民邮电出版社)课后习题答案
  6. Arcgis使用教程(十一)ARCGIS地图制图之经纬网格设置参数详解
  7. 计算机音乐谱巴啦啦小魔,天谕手游巴啦啦小魔仙乐谱代码分享
  8. 基带信号matlab仿真,基带信号仿真方法上篇
  9. 简单易懂应如何快速掌握超长激光测距仪相关性能指标TFNLR20KI激光测距仪带你走进其简单的世界
  10. Symantec Backup Exec 2010 安装报 bad ELF interpreter: No such file or directory