接上一篇文章:高频多线程高并发JUC编程(一)
5、8锁现象
1-2锁
packagecom.zmz.lock8;/***@ProjectName:Juc*@Package:com.zmz.lock8*@ClassName:Test1*@Author:张晟睿*@Date:2021/9/521:18*@Version:1.0*/importjava.util.concurrent.TimeUnit;/***@ClassNameTest1*@Description*@Author张晟睿*@Date2021/9/5**//**8锁,就是关于锁的8个问题*1、标准情况下,两个线程先打印发短信还是打电话?发短信*2、sendSms方法延迟4s,两个线程先打印发短信还是打电话?发短信**/publicclassTest1{publicstaticvoidmain(String[]args){Phonephone=newPhone();//锁存在newThread(()->{phone.sendSms();},"A").start();try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}newThread(()->{phone.call();},"B").start();}}classPhone{//synchronized锁的对象是方法的调用者!//两个方法用的都是phone对象的锁!//谁先拿到谁执行!publicsynchronizedvoidsendSms(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("发短信");}publicsynchronizedvoidcall(){System.out.println("打电话");}}
3-4锁
packagecom.zmz.lock8;/***@ProjectName:Juc*@Package:com.zmz.lock8*@ClassName:Test2*@Author:张晟睿*@Date:2021/9/521:26*@Version:1.0*/importjava.util.concurrent.TimeUnit;/***@ClassNameTest2*@Description*@Author张晟睿*@Date2021/9/5**///3、增加一个普通方法后!发短信还是Hello,发短信hello//4、两个对象,两个同步方法,发短信还是打电话打电话publicclassTest2{publicstaticvoidmain(String[]args){//两个对象,两把锁Phone2phone=newPhone2();Phone2phone2=newPhone2();//锁存在newThread(()->{phone.sendSms();},"A").start();try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}newThread(()->{phone2.call();},"B").start();}}classPhone2{//synchronized锁的对象是方法的调用者!publicsynchronizedvoidsendSms(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("发短信");}publicsynchronizedvoidcall(){System.out.println("打电话");}//这里没有锁!bubu不是同步方法,不受锁的影响publicvoidhello(){System.out.println("hello");}}
5-6锁
packagecom.zmz.lock8;/***@ProjectName:Juc*@Package:com.zmz.lock8*@ClassName:Test3*@Author:张晟睿*@Date:2021/9/612:35*@Version:1.0*/importjava.util.concurrent.TimeUnit;/***@ClassNameTest3*@Description*@Author张晟睿*@Date2021/9/6**//**5、增加两个静态同步方法,只有一个对象,先打印发短信还是打电话?发短信*6、两个对象!增加两个静态同步方法,只有一个对象,先打印发短信还是打电话发短信**/publicclassTest3{publicstaticvoidmain(String[]args){//两个对象,两个调用者,两把锁!//两个对象的class类模板只有一个,static,锁的是ClassPhone3phone=newPhone3();Phone3phone2=newPhone3();//锁存在newThread(()->{phone.sendSms();},"A").start();try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}newThread(()->{phone2.call();},"B").start();}}//Phone3唯一的一个Class对象classPhone3{//synchronized锁的对象是方法的调用者!//static静态方法//类一加载就有了!Class模板锁的是ClasspublicstaticsynchronizedvoidsendSms(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("发短信");}publicstaticsynchronizedvoidcall(){System.out.println("打电话");}}
7-8锁
packagecom.zmz.lock8;/***@ProjectName:Juc*@Package:com.zmz.lock8*@ClassName:Test4*@Author:张晟睿*@Date:2021/9/613:07*@Version:1.0*/importjava.util.concurrent.TimeUnit;/***@ClassNameTest4*@Description*@Author张晟睿*@Date2021/9/6**//**1个静态同步方法,1个同步方法,1个对象先打印发短信还是打电话?打电话*1个静态同步方法,1个同步方法,2个对象先打印发短信还是打电话?发短信**/publicclassTest4{publicstaticvoidmain(String[]args){//两个对象,两个调用者,两把锁!//两个对象的class类模板只有一个,static,锁的是ClassPhone4phone=newPhone4();//锁存在newThread(()->{phone.sendSms();},"A").start();try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}newThread(()->{phone.call();},"B").start();}}//Phone4唯一的一个Class对象classPhone4{//synchronized锁的对象是方法的调用者!//锁的是Class类模板publicstaticsynchronizedvoidsendSms(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("发短信");}//锁的是调用者publicsynchronizedvoidcall(){System.out.println("打电话");}}
6、集合不安全
1、ArrayList集合不安全
packagecom;/***@ProjectName:Juc*@Package:com*@ClassName:unsafe*@Author:张晟睿*@Date:2021/9/619:37*@Version:1.0*/importjava.util.*;importjava.util.concurrent.CopyOnWriteArrayList;/***@ClassNameunsafe*@Description*@Author张晟睿*@Date2021/9/6**/publicclassunsafe{publicstaticvoidmain(String[]args){//高并发下的ArrayList真的安全么?/***解决方法*1、List<String>list=newVector<String>();*2、List<String>list=Collections.synchronizedList(newArrayList<>());*3、List<String>list=newCopyOnWriteArrayList<>();**/List<String>list=newCopyOnWriteArrayList<>();//启动10个多线程for(inti=1;i<10;i++){newThread(()->{list.add(UUID.randomUUID().toString().substring(0,5));System.out.println(list);},String.valueOf(i)).start();}}}
CopyOnWriteArrayList源码分析
2、Set不安全
packagecom.zmz.unsafe;/***@ProjectName:Juc*@Package:com.zmz.unsafe*@ClassName:SetSafe*@Author:张晟睿*@Date:2021/9/621:20*@Version:1.0*/importjava.util.Collections;importjava.util.HashSet;importjava.util.Set;importjava.util.UUID;importjava.util.concurrent.CopyOnWriteArraySet;/***@ClassNameSetSafe*@Description*@Author张晟睿*@Date2021/9/6**/publicclassSetSafe{publicstaticvoidmain(String[]args){//Set<String>set=newHashSet<>();//Set<String>set=Collections.synchronizedSet(newHashSet<>());Set<String>set=newCopyOnWriteArraySet<>();for(inti=1;i<60;i++){newThread(()->{set.add(UUID.randomUUID().toString().substring(0,5));System.out.println(set);},String.valueOf(i)).start();}}}
HashSet源码
publicHashSet(){map=newHashMap<>();}//HashSet本质就是Map集合publicbooleanadd(Ee){returnmap.put(e,PRESENT)==null;}privatestaticfinalObjectPRESENT=newObject();//不变的值
3、HashMap不安全
packagecom.zmz.unsafe;/***@ProjectName:Juc*@Package:com.zmz.unsafe*@ClassName:MapSafe*@Author:张晟睿*@Date:2021/9/621:27*@Version:1.0*/importjava.util.Collections;importjava.util.HashMap;importjava.util.Map;importjava.util.UUID;importjava.util.concurrent.ConcurrentHashMap;/***@ClassNameMapSafe*@Description*@Author张晟睿*@Date2021/9/6**/publicclassMapSafe{publicstaticvoidmain(String[]args){//Map<String,String>map=newHashMap<>();//Map<String,Object>map=Collections.synchronizedMap(newHashMap<>());Map<String,Object>map=newConcurrentHashMap<>();for(inti=1;i<=30;i++){newThread(()->{map.put(Thread.currentThread().getName(),UUID.randomUUID().toString().substring(0,5));System.out.println(map);},String.valueOf(i)).start();}}}
7、Callable
可以有返回值
可以抛出异常
方法不同,run()/call()
callable源码
代码测试
packagecom.zmz.callable;/***@ProjectName:Juc*@Package:com.zmz.callable*@ClassName:CallableTest*@Author:张晟睿*@Date:2021/10/316:52*@Version:1.0*/importcom.sun.org.apache.bcel.internal.generic.NEW;importjava.util.concurrent.Callable;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.FutureTask;/***@ClassNameCallableTest*@Description*@Author张晟睿*@Date2021/10/3**/publicclassCallableTest{publicstaticvoidmain(String[]args)throwsExecutionException,InterruptedException{//newThread(newRunnable()).start();//newThread(newFutureTask<V>()).start();//newThread(newFutureTask<V>(Callable)).start();newThread().start();MyThreadmyThread=newMyThread();FutureTaskfutureTask=newFutureTask(myThread);//适配类newThread(futureTask,"A").start();newThread(futureTask,"B").start();//结果存在缓存提交效率Integero=(Integer)futureTask.get();//获取返回的结果//这个get方法可以会产生阻塞!解决办法放到最后一行或者异步通信System.out.println(o);}}classMyThreadimplementsCallable<Integer>{@OverridepublicIntegercall()throwsException{System.out.println("call()方法");//耗时操作return1024;}}/*1、有缓存2、结果可能会等待,阻塞*/
8、常用的辅助类
1) CountDownLatch—减法计数器
packagecom.zmz.assist;/***@ProjectName:Juc*@Package:com.zmz.assist*@ClassName:CountDownLatchDemo*@Author:张晟睿*@Date:2021/10/318:00*@Version:1.0*/importjava.util.concurrent.CountDownLatch;/***@ClassNameCountDownLatchDemo*@Description*@Author张晟睿*@Date2021/10/3**/publicclassCountDownLatchDemo{publicstaticvoidmain(String[]args)throwsInterruptedException{CountDownLatchcount=newCountDownLatch(10);for(inti=1;i<=10;i++){newThread(()->{System.out.println(Thread.currentThread().getName()+"Goout");count.countDown();//数量-1},String.valueOf(i)).start();}count.await();//等计数器归零,然后再往下执行System.out.println("CloseDoor");}}
原理:
count.countDown();//数量-1
count.await();//等待计数器归零。然后再向下执行
每次有线程用countDown()数量-1,如果计算器变为0了,然后count.await()就被唤醒,继续下面的执行!
2) CyclicBarrier—加法计数器
packagecom.zmz.lock8;/***@ProjectName:Juc*@Package:com.zmz.lock8*@ClassName:Test2*@Author:张晟睿*@Date:2021/9/521:26*@Version:1.0*/importjava.util.concurrent.TimeUnit;/***@ClassNameTest2*@Description*@Author张晟睿*@Date2021/9/5**///3、增加一个普通方法后!发短信还是Hello,发短信hello//4、两个对象,两个同步方法,发短信还是打电话打电话publicclassTest2{publicstaticvoidmain(String[]args){//两个对象,两把锁Phone2phone=newPhone2();Phone2phone2=newPhone2();//锁存在newThread(()->{phone.sendSms();},"A").start();try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}newThread(()->{phone2.call();},"B").start();}}classPhone2{//synchronized锁的对象是方法的调用者!publicsynchronizedvoidsendSms(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("发短信");}publicsynchronizedvoidcall(){System.out.println("打电话");}//这里没有锁!bubu不是同步方法,不受锁的影响publicvoidhello(){System.out.println("hello");}}0
3) Semaphore
Semaphore:信号量,很多时候用来处理高并发。
packagecom.zmz.lock8;/***@ProjectName:Juc*@Package:com.zmz.lock8*@ClassName:Test2*@Author:张晟睿*@Date:2021/9/521:26*@Version:1.0*/importjava.util.concurrent.TimeUnit;/***@ClassNameTest2*@Description*@Author张晟睿*@Date2021/9/5**///3、增加一个普通方法后!发短信还是Hello,发短信hello//4、两个对象,两个同步方法,发短信还是打电话打电话publicclassTest2{publicstaticvoidmain(String[]args){//两个对象,两把锁Phone2phone=newPhone2();Phone2phone2=newPhone2();//锁存在newThread(()->{phone.sendSms();},"A").start();try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}newThread(()->{phone2.call();},"B").start();}}classPhone2{//synchronized锁的对象是方法的调用者!publicsynchronizedvoidsendSms(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("发短信");}publicsynchronizedvoidcall(){System.out.println("打电话");}//这里没有锁!bubu不是同步方法,不受锁的影响publicvoidhello(){System.out.println("hello");}}1
原理:
acquire():获得,假设已经满了组需要等待,直到被释放为止
release():释放,会将当前的信号量释放+1,然后唤醒等待的线程!
作用:多个共享的资源互斥使用!并发限流控制最大的线程数量!
9、读写锁ReadwriteLock
packagecom.zmz.lock8;/***@ProjectName:Juc*@Package:com.zmz.lock8*@ClassName:Test2*@Author:张晟睿*@Date:2021/9/521:26*@Version:1.0*/importjava.util.concurrent.TimeUnit;/***@ClassNameTest2*@Description*@Author张晟睿*@Date2021/9/5**///3、增加一个普通方法后!发短信还是Hello,发短信hello//4、两个对象,两个同步方法,发短信还是打电话打电话publicclassTest2{publicstaticvoidmain(String[]args){//两个对象,两把锁Phone2phone=newPhone2();Phone2phone2=newPhone2();//锁存在newThread(()->{phone.sendSms();},"A").start();try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}newThread(()->{phone2.call();},"B").start();}}classPhone2{//synchronized锁的对象是方法的调用者!publicsynchronizedvoidsendSms(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("发短信");}publicsynchronizedvoidcall(){System.out.println("打电话");}//这里没有锁!bubu不是同步方法,不受锁的影响publicvoidhello(){System.out.println("hello");}}2
我们可以看到出现了严重的插队问题!该如何去解决囊?我们使用读写锁来解决插队的问题。
修改后的操作
packagecom.zmz.lock8;/***@ProjectName:Juc*@Package:com.zmz.lock8*@ClassName:Test2*@Author:张晟睿*@Date:2021/9/521:26*@Version:1.0*/importjava.util.concurrent.TimeUnit;/***@ClassNameTest2*@Description*@Author张晟睿*@Date2021/9/5**///3、增加一个普通方法后!发短信还是Hello,发短信hello//4、两个对象,两个同步方法,发短信还是打电话打电话publicclassTest2{publicstaticvoidmain(String[]args){//两个对象,两把锁Phone2phone=newPhone2();Phone2phone2=newPhone2();//锁存在newThread(()->{phone.sendSms();},"A").start();try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}newThread(()->{phone2.call();},"B").start();}}classPhone2{//synchronized锁的对象是方法的调用者!publicsynchronizedvoidsendSms(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("发短信");}publicsynchronizedvoidcall(){System.out.println("打电话");}//这里没有锁!bubu不是同步方法,不受锁的影响publicvoidhello(){System.out.println("hello");}}3
我们可以看到输出的结果在写入的时候有序的进行,读操作的时候可以无序的进行,可以看到已经到达我们预期的效果?
10、堵塞队列
堵塞
什么情况下我们使用阻塞队列:多线程并发处理,线程池!
10.1 学会使用队列
添加、移除元素,现在有四组API
1) 四组API
packagecom.zmz.lock8;/***@ProjectName:Juc*@Package:com.zmz.lock8*@ClassName:Test2*@Author:张晟睿*@Date:2021/9/521:26*@Version:1.0*/importjava.util.concurrent.TimeUnit;/***@ClassNameTest2*@Description*@Author张晟睿*@Date2021/9/5**///3、增加一个普通方法后!发短信还是Hello,发短信hello//4、两个对象,两个同步方法,发短信还是打电话打电话publicclassTest2{publicstaticvoidmain(String[]args){//两个对象,两把锁Phone2phone=newPhone2();Phone2phone2=newPhone2();//锁存在newThread(()->{phone.sendSms();},"A").start();try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}newThread(()->{phone2.call();},"B").start();}}classPhone2{//synchronized锁的对象是方法的调用者!publicsynchronizedvoidsendSms(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("发短信");}publicsynchronizedvoidcall(){System.out.println("打电话");}//这里没有锁!bubu不是同步方法,不受锁的影响publicvoidhello(){System.out.println("hello");}}4
packagecom.zmz.lock8;/***@ProjectName:Juc*@Package:com.zmz.lock8*@ClassName:Test2*@Author:张晟睿*@Date:2021/9/521:26*@Version:1.0*/importjava.util.concurrent.TimeUnit;/***@ClassNameTest2*@Description*@Author张晟睿*@Date2021/9/5**///3、增加一个普通方法后!发短信还是Hello,发短信hello//4、两个对象,两个同步方法,发短信还是打电话打电话publicclassTest2{publicstaticvoidmain(String[]args){//两个对象,两把锁Phone2phone=newPhone2();Phone2phone2=newPhone2();//锁存在newThread(()->{phone.sendSms();},"A").start();try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}newThread(()->{phone2.call();},"B").start();}}classPhone2{//synchronized锁的对象是方法的调用者!publicsynchronizedvoidsendSms(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("发短信");}publicsynchronizedvoidcall(){System.out.println("打电话");}//这里没有锁!bubu不是同步方法,不受锁的影响publicvoidhello(){System.out.println("hello");}}5
packagecom.zmz.lock8;/***@ProjectName:Juc*@Package:com.zmz.lock8*@ClassName:Test2*@Author:张晟睿*@Date:2021/9/521:26*@Version:1.0*/importjava.util.concurrent.TimeUnit;/***@ClassNameTest2*@Description*@Author张晟睿*@Date2021/9/5**///3、增加一个普通方法后!发短信还是Hello,发短信hello//4、两个对象,两个同步方法,发短信还是打电话打电话publicclassTest2{publicstaticvoidmain(String[]args){//两个对象,两把锁Phone2phone=newPhone2();Phone2phone2=newPhone2();//锁存在newThread(()->{phone.sendSms();},"A").start();try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}newThread(()->{phone2.call();},"B").start();}}classPhone2{//synchronized锁的对象是方法的调用者!publicsynchronizedvoidsendSms(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("发短信");}publicsynchronizedvoidcall(){System.out.println("打电话");}//这里没有锁!bubu不是同步方法,不受锁的影响publicvoidhello(){System.out.println("hello");}}6
packagecom.zmz.lock8;/***@ProjectName:Juc*@Package:com.zmz.lock8*@ClassName:Test2*@Author:张晟睿*@Date:2021/9/521:26*@Version:1.0*/importjava.util.concurrent.TimeUnit;/***@ClassNameTest2*@Description*@Author张晟睿*@Date2021/9/5**///3、增加一个普通方法后!发短信还是Hello,发短信hello//4、两个对象,两个同步方法,发短信还是打电话打电话publicclassTest2{publicstaticvoidmain(String[]args){//两个对象,两把锁Phone2phone=newPhone2();Phone2phone2=newPhone2();//锁存在newThread(()->{phone.sendSms();},"A").start();try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}newThread(()->{phone2.call();},"B").start();}}classPhone2{//synchronized锁的对象是方法的调用者!publicsynchronizedvoidsendSms(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("发短信");}publicsynchronizedvoidcall(){System.out.println("打电话");}//这里没有锁!bubu不是同步方法,不受锁的影响publicvoidhello(){System.out.println("hello");}}7
2) SynchronizedQueue 同步队列
没有容量,进去一个元素,必须等待取出来之后,才能再往里面放一个元素
put take
packagecom.zmz.lock8;/***@ProjectName:Juc*@Package:com.zmz.lock8*@ClassName:Test2*@Author:张晟睿*@Date:2021/9/521:26*@Version:1.0*/importjava.util.concurrent.TimeUnit;/***@ClassNameTest2*@Description*@Author张晟睿*@Date2021/9/5**///3、增加一个普通方法后!发短信还是Hello,发短信hello//4、两个对象,两个同步方法,发短信还是打电话打电话publicclassTest2{publicstaticvoidmain(String[]args){//两个对象,两把锁Phone2phone=newPhone2();Phone2phone2=newPhone2();//锁存在newThread(()->{phone.sendSms();},"A").start();try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}newThread(()->{phone2.call();},"B").start();}}classPhone2{//synchronized锁的对象是方法的调用者!publicsynchronizedvoidsendSms(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("发短信");}publicsynchronizedvoidcall(){System.out.println("打电话");}//这里没有锁!bubu不是同步方法,不受锁的影响publicvoidhello(){System.out.println("hello");}}8
11、线程池
线程池有三大方法,七大参数,四种拒绝策略
程序的运行,本质: 占用系统的资源 ! 优化CPU资源的使用 ===>池化技术
线程池, 连接池, 内存池, 对象池///…
池化技术: 实现准备好一些资源, 有人要用,就来我这里拿,用完之后还给我
1) 线程池的好处:
降低资源消耗
提高响应速度
方便管理
线程复用,可以控制最大并发数,管理线程
2) 线程池: 三大方法
ExecutorService service = Executors.newSingleThreadExecutor();//单个线程
ExecutorService service = Executors.newFixedThreadPool(5);//创建一个固定的线程池的大小
ExecutorService service = Executors.newCachedThreadPool();//可伸缩的,
packagecom.zmz.lock8;/***@ProjectName:Juc*@Package:com.zmz.lock8*@ClassName:Test2*@Author:张晟睿*@Date:2021/9/521:26*@Version:1.0*/importjava.util.concurrent.TimeUnit;/***@ClassNameTest2*@Description*@Author张晟睿*@Date2021/9/5**///3、增加一个普通方法后!发短信还是Hello,发短信hello//4、两个对象,两个同步方法,发短信还是打电话打电话publicclassTest2{publicstaticvoidmain(String[]args){//两个对象,两把锁Phone2phone=newPhone2();Phone2phone2=newPhone2();//锁存在newThread(()->{phone.sendSms();},"A").start();try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}newThread(()->{phone2.call();},"B").start();}}classPhone2{//synchronized锁的对象是方法的调用者!publicsynchronizedvoidsendSms(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("发短信");}publicsynchronizedvoidcall(){System.out.println("打电话");}//这里没有锁!bubu不是同步方法,不受锁的影响publicvoidhello(){System.out.println("hello");}}9
3) 七大参数
packagecom.zmz.lock8;/***@ProjectName:Juc*@Package:com.zmz.lock8*@ClassName:Test3*@Author:张晟睿*@Date:2021/9/612:35*@Version:1.0*/importjava.util.concurrent.TimeUnit;/***@ClassNameTest3*@Description*@Author张晟睿*@Date2021/9/6**//**5、增加两个静态同步方法,只有一个对象,先打印发短信还是打电话?发短信*6、两个对象!增加两个静态同步方法,只有一个对象,先打印发短信还是打电话发短信**/publicclassTest3{publicstaticvoidmain(String[]args){//两个对象,两个调用者,两把锁!//两个对象的class类模板只有一个,static,锁的是ClassPhone3phone=newPhone3();Phone3phone2=newPhone3();//锁存在newThread(()->{phone.sendSms();},"A").start();try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}newThread(()->{phone2.call();},"B").start();}}//Phone3唯一的一个Class对象classPhone3{//synchronized锁的对象是方法的调用者!//static静态方法//类一加载就有了!Class模板锁的是ClasspublicstaticsynchronizedvoidsendSms(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("发短信");}publicstaticsynchronizedvoidcall(){System.out.println("打电话");}}0
packagecom.zmz.lock8;/***@ProjectName:Juc*@Package:com.zmz.lock8*@ClassName:Test3*@Author:张晟睿*@Date:2021/9/612:35*@Version:1.0*/importjava.util.concurrent.TimeUnit;/***@ClassNameTest3*@Description*@Author张晟睿*@Date2021/9/6**//**5、增加两个静态同步方法,只有一个对象,先打印发短信还是打电话?发短信*6、两个对象!增加两个静态同步方法,只有一个对象,先打印发短信还是打电话发短信**/publicclassTest3{publicstaticvoidmain(String[]args){//两个对象,两个调用者,两把锁!//两个对象的class类模板只有一个,static,锁的是ClassPhone3phone=newPhone3();Phone3phone2=newPhone3();//锁存在newThread(()->{phone.sendSms();},"A").start();try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}newThread(()->{phone2.call();},"B").start();}}//Phone3唯一的一个Class对象classPhone3{//synchronized锁的对象是方法的调用者!//static静态方法//类一加载就有了!Class模板锁的是ClasspublicstaticsynchronizedvoidsendSms(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("发短信");}publicstaticsynchronizedvoidcall(){System.out.println("打电话");}}1
4) 拒绝策略
new ThreadPoolExecutor.AbortPolicy() 超出最大处理线程抛出异常
new ThreadPoolExecutor.CallerRunsPolicy() 从哪个线程创建就由那个线程执行
new ThreadPoolExecutor.DiscardPolicy() 队列满了不会抛出异常
new ThreadPoolExecutor.DiscardOldestPolicy() 尝试去和第一个竞争,也不会抛出异常
12、四大函数式接口
新时代的程序员??:lambda表达式、链式编程、函数式接口、Stream流式计算
1) Function函数型接口
packagecom.zmz.lock8;/***@ProjectName:Juc*@Package:com.zmz.lock8*@ClassName:Test3*@Author:张晟睿*@Date:2021/9/612:35*@Version:1.0*/importjava.util.concurrent.TimeUnit;/***@ClassNameTest3*@Description*@Author张晟睿*@Date2021/9/6**//**5、增加两个静态同步方法,只有一个对象,先打印发短信还是打电话?发短信*6、两个对象!增加两个静态同步方法,只有一个对象,先打印发短信还是打电话发短信**/publicclassTest3{publicstaticvoidmain(String[]args){//两个对象,两个调用者,两把锁!//两个对象的class类模板只有一个,static,锁的是ClassPhone3phone=newPhone3();Phone3phone2=newPhone3();//锁存在newThread(()->{phone.sendSms();},"A").start();try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}newThread(()->{phone2.call();},"B").start();}}//Phone3唯一的一个Class对象classPhone3{//synchronized锁的对象是方法的调用者!//static静态方法//类一加载就有了!Class模板锁的是ClasspublicstaticsynchronizedvoidsendSms(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("发短信");}publicstaticsynchronizedvoidcall(){System.out.println("打电话");}}2
2) Predicate 断定型接口
packagecom.zmz.lock8;/***@ProjectName:Juc*@Package:com.zmz.lock8*@ClassName:Test3*@Author:张晟睿*@Date:2021/9/612:35*@Version:1.0*/importjava.util.concurrent.TimeUnit;/***@ClassNameTest3*@Description*@Author张晟睿*@Date2021/9/6**//**5、增加两个静态同步方法,只有一个对象,先打印发短信还是打电话?发短信*6、两个对象!增加两个静态同步方法,只有一个对象,先打印发短信还是打电话发短信**/publicclassTest3{publicstaticvoidmain(String[]args){//两个对象,两个调用者,两把锁!//两个对象的class类模板只有一个,static,锁的是ClassPhone3phone=newPhone3();Phone3phone2=newPhone3();//锁存在newThread(()->{phone.sendSms();},"A").start();try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}newThread(()->{phone2.call();},"B").start();}}//Phone3唯一的一个Class对象classPhone3{//synchronized锁的对象是方法的调用者!//static静态方法//类一加载就有了!Class模板锁的是ClasspublicstaticsynchronizedvoidsendSms(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("发短信");}publicstaticsynchronizedvoidcall(){System.out.println("打电话");}}3
3) Suppier 供给型接口
packagecom.zmz.lock8;/***@ProjectName:Juc*@Package:com.zmz.lock8*@ClassName:Test3*@Author:张晟睿*@Date:2021/9/612:35*@Version:1.0*/importjava.util.concurrent.TimeUnit;/***@ClassNameTest3*@Description*@Author张晟睿*@Date2021/9/6**//**5、增加两个静态同步方法,只有一个对象,先打印发短信还是打电话?发短信*6、两个对象!增加两个静态同步方法,只有一个对象,先打印发短信还是打电话发短信**/publicclassTest3{publicstaticvoidmain(String[]args){//两个对象,两个调用者,两把锁!//两个对象的class类模板只有一个,static,锁的是ClassPhone3phone=newPhone3();Phone3phone2=newPhone3();//锁存在newThread(()->{phone.sendSms();},"A").start();try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}newThread(()->{phone2.call();},"B").start();}}//Phone3唯一的一个Class对象classPhone3{//synchronized锁的对象是方法的调用者!//static静态方法//类一加载就有了!Class模板锁的是ClasspublicstaticsynchronizedvoidsendSms(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("发短信");}publicstaticsynchronizedvoidcall(){System.out.println("打电话");}}4
4) Consummer 消费型接口
packagecom.zmz.lock8;/***@ProjectName:Juc*@Package:com.zmz.lock8*@ClassName:Test3*@Author:张晟睿*@Date:2021/9/612:35*@Version:1.0*/importjava.util.concurrent.TimeUnit;/***@ClassNameTest3*@Description*@Author张晟睿*@Date2021/9/6**//**5、增加两个静态同步方法,只有一个对象,先打印发短信还是打电话?发短信*6、两个对象!增加两个静态同步方法,只有一个对象,先打印发短信还是打电话发短信**/publicclassTest3{publicstaticvoidmain(String[]args){//两个对象,两个调用者,两把锁!//两个对象的class类模板只有一个,static,锁的是ClassPhone3phone=newPhone3();Phone3phone2=newPhone3();//锁存在newThread(()->{phone.sendSms();},"A").start();try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}newThread(()->{phone2.call();},"B").start();}}//Phone3唯一的一个Class对象classPhone3{//synchronized锁的对象是方法的调用者!//static静态方法//类一加载就有了!Class模板锁的是ClasspublicstaticsynchronizedvoidsendSms(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("发短信");}publicstaticsynchronizedvoidcall(){System.out.println("打电话");}}5
13、Stream 流式计算
packagecom.zmz.lock8;/***@ProjectName:Juc*@Package:com.zmz.lock8*@ClassName:Test3*@Author:张晟睿*@Date:2021/9/612:35*@Version:1.0*/importjava.util.concurrent.TimeUnit;/***@ClassNameTest3*@Description*@Author张晟睿*@Date2021/9/6**//**5、增加两个静态同步方法,只有一个对象,先打印发短信还是打电话?发短信*6、两个对象!增加两个静态同步方法,只有一个对象,先打印发短信还是打电话发短信**/publicclassTest3{publicstaticvoidmain(String[]args){//两个对象,两个调用者,两把锁!//两个对象的class类模板只有一个,static,锁的是ClassPhone3phone=newPhone3();Phone3phone2=newPhone3();//锁存在newThread(()->{phone.sendSms();},"A").start();try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}newThread(()->{phone2.call();},"B").start();}}//Phone3唯一的一个Class对象classPhone3{//synchronized锁的对象是方法的调用者!//static静态方法//类一加载就有了!Class模板锁的是ClasspublicstaticsynchronizedvoidsendSms(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("发短信");}publicstaticsynchronizedvoidcall(){System.out.println("打电话");}}6
packagecom.zmz.lock8;/***@ProjectName:Juc*@Package:com.zmz.lock8*@ClassName:Test3*@Author:张晟睿*@Date:2021/9/612:35*@Version:1.0*/importjava.util.concurrent.TimeUnit;/***@ClassNameTest3*@Description*@Author张晟睿*@Date2021/9/6**//**5、增加两个静态同步方法,只有一个对象,先打印发短信还是打电话?发短信*6、两个对象!增加两个静态同步方法,只有一个对象,先打印发短信还是打电话发短信**/publicclassTest3{publicstaticvoidmain(String[]args){//两个对象,两个调用者,两把锁!//两个对象的class类模板只有一个,static,锁的是ClassPhone3phone=newPhone3();Phone3phone2=newPhone3();//锁存在newThread(()->{phone.sendSms();},"A").start();try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}newThread(()->{phone2.call();},"B").start();}}//Phone3唯一的一个Class对象classPhone3{//synchronized锁的对象是方法的调用者!//static静态方法//类一加载就有了!Class模板锁的是ClasspublicstaticsynchronizedvoidsendSms(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("发短信");}publicstaticsynchronizedvoidcall(){System.out.println("打电话");}}7
14、ForkJoin—多线并发处理框架
什么是ForkJoin?
ava.util.concurrent.ForkJoinPool由Java大师Doug Lea主持编写,它可以将一个大的任务拆分成多个子任务进行并行处理,最后将子任务结果合并成最后的计算结果,并进行输出。本文中对Fork/Join框架的讲解,基于JDK1.8+中的Fork/Join框架实现,参考的Fork/Join框架主要源代码也基于JDK1.8+。
这几篇文章将试图解释Fork/Join框架的知识点,以便对自己、对各位读者在并发程序的设计思路上进行一些启发。文章将首先讲解Fork/Join框架的基本使用,以及其中需要注意的使用要点;接着使用Fork/Join框架解决一些实际问题;最后再讲解Fork/Join框架的工作原理。
1)ForkJoin 特点: 工作窃取!
2)如果使用ForkJoin
第一步,通过ForkJoinPool来执行
第二步,计算任务 execute(ForkJoinTask<?> task)
第三步,计算类要去继承ForkJoinTask
ForkJoin 的计算类
ForkJoinComputer.java
packagecom.zmz.lock8;/***@ProjectName:Juc*@Package:com.zmz.lock8*@ClassName:Test3*@Author:张晟睿*@Date:2021/9/612:35*@Version:1.0*/importjava.util.concurrent.TimeUnit;/***@ClassNameTest3*@Description*@Author张晟睿*@Date2021/9/6**//**5、增加两个静态同步方法,只有一个对象,先打印发短信还是打电话?发短信*6、两个对象!增加两个静态同步方法,只有一个对象,先打印发短信还是打电话发短信**/publicclassTest3{publicstaticvoidmain(String[]args){//两个对象,两个调用者,两把锁!//两个对象的class类模板只有一个,static,锁的是ClassPhone3phone=newPhone3();Phone3phone2=newPhone3();//锁存在newThread(()->{phone.sendSms();},"A").start();try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}newThread(()->{phone2.call();},"B").start();}}//Phone3唯一的一个Class对象classPhone3{//synchronized锁的对象是方法的调用者!//static静态方法//类一加载就有了!Class模板锁的是ClasspublicstaticsynchronizedvoidsendSms(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("发短信");}publicstaticsynchronizedvoidcall(){System.out.println("打电话");}}8
测试类 ForkJoinTest.java
packagecom.zmz.lock8;/***@ProjectName:Juc*@Package:com.zmz.lock8*@ClassName:Test3*@Author:张晟睿*@Date:2021/9/612:35*@Version:1.0*/importjava.util.concurrent.TimeUnit;/***@ClassNameTest3*@Description*@Author张晟睿*@Date2021/9/6**//**5、增加两个静态同步方法,只有一个对象,先打印发短信还是打电话?发短信*6、两个对象!增加两个静态同步方法,只有一个对象,先打印发短信还是打电话发短信**/publicclassTest3{publicstaticvoidmain(String[]args){//两个对象,两个调用者,两把锁!//两个对象的class类模板只有一个,static,锁的是ClassPhone3phone=newPhone3();Phone3phone2=newPhone3();//锁存在newThread(()->{phone.sendSms();},"A").start();try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}newThread(()->{phone2.call();},"B").start();}}//Phone3唯一的一个Class对象classPhone3{//synchronized锁的对象是方法的调用者!//static静态方法//类一加载就有了!Class模板锁的是ClasspublicstaticsynchronizedvoidsendSms(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("发短信");}publicstaticsynchronizedvoidcall(){System.out.println("打电话");}}9
分析一下高级程序猿的处理:
.parallel().reduce(0, Long::sum)使用一个并行流去计算整个计算,提高效率。