Java--JUC--复习
- JUC是什么:java并发编程中使用的工具类
- java.util.concurrent
- java.util.concurrent.atomic
- java.util.concurrent.locks
- 什么是进程什么是线程
-
- 什么是并发/并行
- 多个线程同时调用同一个资源类
- 同时做多件事
- 生产者消费和模式 为了防止虚假唤醒,我们应该使用while进行判断,每次都重新过一次安检,如果是if的换会出现虚假唤醒导致一加一减的业务逻辑失败。
-
package com.model.new_concurrent; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * 启动:ABC三个线程 * 要求A打印5次 ,b打印10次,c打印15次 * 来十轮 * * */ class Print{ private int num=1; Lock lock=new ReentrantLock(); Condition condition_a=lock.newCondition(); Condition condition_b=lock.newCondition(); Condition condition_c=lock.newCondition(); public void print_a(){ lock.lock(); try { while(num!=1){ condition_a.await(); } num++; for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName()+"打印了"+i); } condition_b.signal(); }catch (Exception e){ e.printStackTrace(); }finally { lock.unlock(); } } public void print_b(){ lock.lock(); try { while(num!=2){ condition_b.await(); } num++; for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName()+"打印了"+i); } condition_c.signal(); }catch (Exception e){ e.printStackTrace(); }finally { lock.unlock(); } } public void print_c(){ lock.lock(); try { while(num!=3){ condition_c.await(); } num=1; for (int i = 0; i < 15; i++) { System.out.println(Thread.currentThread().getName()+"打印了"+i); } condition_a.signal(); }catch (Exception e){ e.printStackTrace(); }finally { lock.unlock(); } } } public class Test01 { public static void main(String[] args) { Print print=new Print(); new Thread(() ->{ for (int i = 0; i < 10; i++) { print.print_a(); } },"A").start(); new Thread(() ->{ for (int i = 0; i < 10; i++) { print.print_b(); } },"B").start(); new Thread(() ->{ for (int i = 0; i < 10; i++) { print.print_c(); } },"C").start(); } }
- 锁机制,同一个对象的所有同步方法不一把锁,所有对象的静态同步方法一把锁
- 集合线程的安全list,set,map
-
package com.model.new_concurrent; import jdk.nashorn.internal.ir.IdentNode; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Vector; import java.util.concurrent.CopyOnWriteArrayList; public class NotSafe_ArrayList { public static void main(String[] args) { // List<Integer> list=new ArrayList<>(); // List<Integer> list=new Vector<>(); // List<Integer> list= Collections.synchronizedList(new ArrayList<>()); List<Integer> list= new CopyOnWriteArrayList();//写时复制 new Thread(() ->{ for (int i = 0; i < 10; i++) { list.add(i); System.out.println(list); } },"A").start(); new Thread(() ->{ for (int i = 0; i < 10; i++) { list.add(i); System.out.println(list); } },"B").start(); } }
-
- 集合的线程安全使用写时复制的方式实现了线程安全,CopyonWritArraylist(),读写不在同一个同其中,写的时候将原来的复制一份,写完之后将 要来的容器的引用指向新版的集合,这样做的可以实现了并发的读而不需要加任何的锁,时读写分离的一种实现
- HashSet的底层时HashMap,只不过set的value值是一个Ojdect类型的常量,HashSet的add方法调用的就是map的put方法
- HashMap的底层是数组,列表,红黑树
-
package com.model.new_concurrent; import jdk.nashorn.internal.ir.IdentNode; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; public class NotSafe_ArrayList { public static void main(String[] args) { // List<Integer> list=new ArrayList<>(); // List<Integer> list=new Vector<>(); // List<Integer> list= Collections.synchronizedList(new ArrayList<>()); List<Integer> list= new CopyOnWriteArrayList();//写时复制 new Thread(() ->{ for (int i = 0; i < 10; i++) { list.add(i); System.out.println(list); } },"A").start(); new Thread(() ->{ for (int i = 0; i < 10; i++) { list.add(i); System.out.println(list); } },"B").start(); } } class NotSafe_HashSet{ public static void main(String[] args) { // List<Integer> list=new ArrayList<>(); // List<Integer> list=new Vector<>(); // List<Integer> list= Collections.synchronizedList(new ArrayList<>()); Set<Integer> set= new CopyOnWriteArraySet();//写时复制 new Thread(() ->{ for (int i = 0; i < 10; i++) { set.add(i); System.out.println(set); } },"A").start(); new Thread(() ->{ for (int i = 0; i < 10; i++) { set.add(i); System.out.println(set); } },"B").start(); } } class NotSafe_HashMap{ public static void main(String[] args) { // List<Integer> list=new ArrayList<>(); // List<Integer> list=new Vector<>(); // List<Integer> list= Collections.synchronizedList(new ArrayList<>()); Map<String,Object> map=new ConcurrentHashMap();//写时复制 new Thread(() ->{ for (int i = 0; i < 10; i++) { map.put(UUID.randomUUID().toString().substring(0,6),i); System.out.println(map); } },"A").start(); new Thread(() ->{ for (int i = 0; i < 10; i++) { map.put(UUID.randomUUID().toString().substring(0,6),i); System.out.println(map); } },"B").start(); } }
-
- 线程实现的第三种方式Callable
-
package com.model.new_concurrent; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; class MyThread01 extends Thread{ @Override public void run() { super.run(); } } class MyThread02 implements Runnable{ @Override public void run() { } } class MyThread03 implements Callable<Integer> { @Override public Integer call() throws Exception { System.out.println("come in *********"); TimeUnit.SECONDS.sleep(4); return 1024; } } public class CallableTest { /** * sleep和wait的区别: * 1.是否有异常 * 2.使用位置 * 3.是否释放锁 * 4.所属类不同 * * Runnable和Callable的区别: * 1.Callable是第三种实现线程方法,Runnable是第二种实现线程的方法 * 2.方法不同:一个叫run方法 ,一个叫call方法 * 3.call方法右异常,run方法无异常 * 4.call方法有返回值,run方法无返回值 * * */ public static void main(String[] args) throws ExecutionException, InterruptedException { // FutureTask 有构造方法可以接受实现了Runnable或者是Callable的接口的类 // FutureTask又是Runnable接口的子类(RunnableFuture)的实现类, // Thread()可以接手Runnable接口的实现类,所有FutureTask的对象可以传入,实现了Runnable和CallAble接口的联系,线程实现成功 // Callable实现的线程:耗时的线程对于主线程来说,如果等待可能会阻塞整体的的推进,整个进程耗时严重 // 使用了Callable实现的线程我们可以为他们另开一个线程,让这个耗时的线程进行着,而我们的主线程不会等待,而是继续往下推进执行, // 当耗时的线程执行完毕之后将放回值返回给主线程即可。这样降低了我们整个程序的执行时间 FutureTask futureTask=new FutureTask(new MyThread03()); new Thread(futureTask,"A").start(); //不管调用几次,只有一个futureTask对象会产生缓存,最终结果执行一次 new Thread(futureTask,"B").start(); System.out.println("****** main线程完成了"); System.out.println(futureTask.get()); //获取返回值,要在程序的最后调用返回值,如果我们刚开启耗时线程,他还没有计算出结果。 // 我们就去调用结果,会造成我们进入这个线程,就要等待他计算完才能出这个线程,造成阻塞,无法达到我们预期的结果 } }
-
- CountDownLatCh的使用(做减法,六个线程都结束,才能完成主线程)
-
package com.model.new_concurrent; import java.util.concurrent.CountDownLatch; class CloseDoor{ public void close(){ System.out.println(Thread.currentThread().getName()+"离开可教室"); } } /** * 实现了一个 等6个进程都完成之后主进程才能结束的逻辑 * CountDownLatch * * */ public class CountDownLatchDemo { public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch=new CountDownLatch(6); CloseDoor closeDoor=new CloseDoor(); for (int i=1;i<=6;i++){ new Thread(() ->{ closeDoor.close(); countDownLatch.countDown(); },String.valueOf(i)).start(); } countDownLatch.await(); System.out.println("班长关门了***"); } }
-
- CyclicBarrier工具类的使用:(做加法:需要完成七个进程才能进行下面的进程)
-
package com.model.new_concurrent; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; /** * * * */ public class CyclicBarrierDemo { /** * 实现了 完成7个及龙珠的线程之后才能进行 召唤神龙的线程的 业务逻辑(都是非主线程) * */ public static void main(String[] args) { CyclicBarrier cyclicBarrier=new CyclicBarrier(7,()->{ System.out.println("收集了7颗龙珠,召唤神龙"); }); for (int i=1;i<=7;i++){ final int t=i; new Thread(() ->{ System.out.println(Thread.currentThread().getName()+"线程收集了第"+t+"颗龙珠"); try { cyclicBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } },String.valueOf(i)).start(); } } }
-
- Semaphore(红绿灯的使用):多个线程争抢多个资源,
-
package com.model.new_concurrent; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; public class SemaphoreDemo { /** * 用于实现多个线程,争抢多个资源的情况(限流) * 当资源数量为1是,就像相当于在资源类中加锁一样的情况 * */ public static void main(String[] args) { Semaphore semaphore=new Semaphore(3); //设置资源数量 for (int i = 1; i <= 6; i++) { new Thread(() ->{ try { semaphore.acquire(); System.out.println(Thread.currentThread().getName()+"抢到了资源"); TimeUnit.SECONDS.sleep(3); semaphore.release(); System.out.println(Thread.currentThread().getName()+"使用完毕 ,释放了资源"); } catch (InterruptedException e) { e.printStackTrace(); } },String.valueOf(i)).start(); } } }
-
- Condition:Condition condition=lock.newCondition(); 指定某一个特定的下一个要执行的线程;callable接口,实现线程的第三种方式(要使用futureTask类);
- collection:set和list的实现的接口;collections:是一个实现排序加索,工具类