zoukankan      html  css  js  c++  java
  • JUC02

    JUC02

    8.读写锁

    package com.mjh.rw;
    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReadWriteLock;
    import java.util.concurrent.locks.ReentrantLock;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    
    /*
    独占锁(写锁)一次只能被一个线程占有
    共享锁(读锁)多个线程可以同时占有
     ReadWriteLock
     读-读  可以共存
     读-写  不能共存
     写-写  不能共存
    */
    public class ReadWriteLockDemo {
        public static void main(String[] args) {
            MyCache1 myCache = new MyCache1();
            //写入
            for (int i = 0; i <=5 ; i++) {
                final int temp=i;
                new Thread(()->{
                    myCache.put(temp+"",temp+"");
                },String.valueOf(i)).start();
            }
    
            //读取
            for (int i = 0; i <=5 ; i++) {
                final int temp=i;
                new Thread(()->{
                    myCache.get(temp+"");
                },String.valueOf(i)).start();
            }
        }
    }
    
    class MyCache{
        private volatile Map<String,Object> map= new HashMap<>();
    
        //存,写
        public void put(String key,Object value){
            System.out.println(Thread.currentThread().getName()+" 写入"+key);
            map.put(key,value);
            System.out.println(Thread.currentThread().getName()+" 写入成功");
        }
    
        //取,读
        public void get(String key){
            System.out.println(Thread.currentThread().getName()+" 读物"+key);
            Object o = map.get(key);
            System.out.println(Thread.currentThread().getName()+" 读取成功");
        }
    }
    
    class MyCache1{
        private volatile Map<String,Object> map= new HashMap<>();
        //读写锁:更加细粒度的控制
        private ReadWriteLock readWriteLock=new ReentrantReadWriteLock();
        //private Lock lock=new ReentrantLock();//普通锁
    
        //存,写的时候,只希望同时只有一个线程写
        public void put(String key,Object value){
             //lock.lock();
            readWriteLock.writeLock().lock();
            try {
    
                System.out.println(Thread.currentThread().getName()+" 写入"+key);
                map.put(key,value);
                System.out.println(Thread.currentThread().getName()+" 写入成功");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                readWriteLock.writeLock().unlock();
            }
    
        }
    
        //取,读
        public void get(String key){
            readWriteLock.readLock().lock();
            try {
                System.out.println(Thread.currentThread().getName()+" 读取"+key);
                Object o = map.get(key);
                System.out.println(Thread.currentThread().getName()+" 读取成功");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                readWriteLock.readLock().unlock();
            }
    
        }
    }
    

    9.阻塞队列

    阻塞队列


    • BlockingQueue  不是新东西
      

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

    学会使用队列

    添加 移除

    四组API

    1.抛出异常

    package com.mjh.bq;
    
    import java.security.spec.RSAOtherPrimeInfo;
    import java.util.concurrent.ArrayBlockingQueue;
    //抛出异常
    public class Demo {
        public static void main(String[] args) {
            test1();
        }
        public static void test1(){
            //队列的大小
            ArrayBlockingQueue<Object> blockingQueue = new ArrayBlockingQueue<>(3);
    
            System.out.println(blockingQueue.add("A"));
            System.out.println(blockingQueue.add("B"));
            System.out.println(blockingQueue.add("C"));
            //java.lang.IllegalStateException: Queue full
           // System.out.println(blockingQueue.add("D"));
            System.out.println(blockingQueue.element());//查询队首元素
            System.out.println("======================");
    
            System.out.println(blockingQueue.remove());
            System.out.println(blockingQueue.remove());
            System.out.println(blockingQueue.remove());
    
            //java.util.NoSuchElementException
           // System.out.println(blockingQueue.remove());
        }
    }
    

    2.不会抛出异常,返回一个特殊值

    //不会抛出异常,返回一个特殊值
        public static void test2(){
            //队列大小
            ArrayBlockingQueue 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("A"));//false  不抛出异常
            System.out.println(blockingQueue.peek());//查询队首元素
            System.out.println("=======================");
            System.out.println(blockingQueue.poll());
            System.out.println(blockingQueue.poll());
            System.out.println(blockingQueue.poll());
    
            // System.out.println(blockingQueue.poll());// null  不抛出异常
    
        }
    

    3.阻塞等待

    /*
    阻塞等待
     */
    public static void test3() throws InterruptedException {
        //队列大小
        ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
    
        blockingQueue.put("A");
        blockingQueue.put("B");
        blockingQueue.put("C");
        //blockingQueue.put("C");//队列没有位置了,一直等待
    
        System.out.println(blockingQueue.take());
        System.out.println(blockingQueue.take());
        System.out.println(blockingQueue.take());
       // System.out.println(blockingQueue.take()); //没有这个元素,一直等待
    }
    

    4.超时等待

    /*
    超时等待
     */
    public static void test4() throws InterruptedException {
        //队列的大小
        ArrayBlockingQueue 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",5, TimeUnit.SECONDS));//等待超过5秒就退出
    
        System.out.println("======================");
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll(5,TimeUnit.SECONDS));//等待超过5秒就退出
    
    }
    

    SynchronousQueue 同步队列

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

    10.线程池(重点)

    线程池技术:三大方法、7大参数、4种拒绝策略

    池化技术

    程序的运行,本质:占用系统的资源!优化资源的使用!=>用池化技术

    线程池、连接池、内存池、对象池。。。。创建、销毁,十分浪费资源

    池化技术:事先准备好一些资源,有人要用,就来我这里拿,用完之后还给我。

    线程池的好处:

    1、降低资源的消耗

    2、提高响应的速度

    3、方便管理

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

    线程池:三大方法

    package com.mjh.pool;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    //Executors 工具类
    public class Demo {
        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 <100 ; 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.corePoolSize = corePoolSize;
            this.maximumPoolSize = maximumPoolSize;
            this.workQueue = workQueue;
            this.keepAliveTime = unit.toNanos(keepAliveTime);
            this.threadFactory = threadFactory;
            this.handler = handler;
        }
    

    手动创建

    package com.mjh.pool;
    
    import java.util.concurrent.*;
    
    //Executors 工具类
    
    /*
    new ThreadPoolExecutor.AbortPolicy());//银行满了,还有人进来,有权不处理这个人的业务,抛出异常
    new ThreadPoolExecutor.CallerRunsPolicy());//哪里来的回哪里去
    new ThreadPoolExecutor.DiscardPolicy());//队列满了,剩余自动丢弃,不会抛出异常
    new ThreadPoolExecutor.DiscardOldestPolicy());//队列满了,尝试去和最早的竞争,不会抛出异常
     */
    
    public class Demo {
        public static void main(String[] args) {
       
            ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
                    2,//核心窗口
                    5,//最大窗口数量
                    3,//超时时间   银行有五个窗口开着,今天人少,有三个窗口是空闲的,这三个窗口在三秒后关闭
                    TimeUnit.SECONDS,//超时单元
                    new LinkedBlockingDeque<>(3),//候客区
                    Executors.defaultThreadFactory(),//线程工厂,一般不用动
                    new ThreadPoolExecutor.DiscardOldestPolicy());//队列满了,尝试去和最早的竞争,不会抛出异常
    
            try {
                //最大承载:Deque+max
                //超过了RejectedExecutionException 异常
                for (int i = 0; i <9; i++) {
                    //使用了线程池之后,使用线程池来创建对象
                    threadPool.execute(()->{
                        System.out.println(Thread.currentThread().getName()+" OK");
                    });
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //线程池用完,程序结束,关闭线程池
                threadPool.shutdown();
            }
        }
    }
    

    4 大拒绝策略

    new ThreadPoolExecutor.AbortPolicy());//银行满了,还有人进来,有权不处理这个人的业务,抛出异常
    new ThreadPoolExecutor.CallerRunsPolicy());//哪里来的回哪里去
    new ThreadPoolExecutor.DiscardPolicy());//队列满了,剩余自动丢弃,不会抛出异常
    new ThreadPoolExecutor.DiscardOldestPolicy());//队列满了,尝试去和最早的竞争,不会抛出异常
    

    IO密集型和CPU密集型

    最大线程到底该如何定义

    package com.mjh.pool;
    
    import java.util.concurrent.*;
    
    //Executors 工具类
    
    public class Demo {
        public static void main(String[] args) {
       
    /**
     * 自定义线程池 工作中使用  ThreadPoolExecutor
     *
     * 最大线程到底该如何定义
     * 1.cpu 密集型,几核,就是几,可以保持CPU的效率最高!
     * 2.IO  密集型  > 判断你程序中十分好IO的线程
     * 程序   15大型任务   IO十分占用资源
     */
            System.out.println(Runtime.getRuntime().availableProcessors());
            ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
                    2,//核心窗口
                   Runtime.getRuntime().availableProcessors(),//可利用处理器
                    3,//超时时间   银行有五个窗口开着,今天人少,有三个窗口是空闲的,这三个窗口在三秒后关闭
                    TimeUnit.SECONDS,//超时单元
                    new LinkedBlockingDeque<>(3),//候客区
                    Executors.defaultThreadFactory(),//线程工厂,一般不用动
                    new ThreadPoolExecutor.DiscardOldestPolicy());//队列满了,尝试去和最早的竞争,不会抛出异常
    
            try {
                //最大承载:Deque+max
                //超过了RejectedExecutionException 异常
                for (int i = 0; i <9; i++) {
                    //使用了线程池之后,使用线程池来创建对象
                    threadPool.execute(()->{
                        System.out.println(Thread.currentThread().getName()+" OK");
                    });
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //线程池用完,程序结束,关闭线程池
                threadPool.shutdown();
            }
        }
    }
    
    
    

    11 .四大函数式接口(必须掌握)

    新时代的程序员:lambda表达式、链式编程、函数式接口、Stream流式计算

    函数式接口:只有一个方法的接口

    @FunctionalInterface
    public interface Runnable {
        public abstract void run();
    }
    //传统程序员:泛型  枚举  反射
    //超级多的@FunctionalInterface
    //简化编程模型,在新版本的框架底层大量使用
    //foreach(消费者类函数式接口)
    

    Function函数式接口

    package com.mjh.function;
    
    import java.util.function.Function;
    
    /**
     * Function  函数式接口  只有一个输入参数,一个输出
     * 只要是  函数式接口  可以用lambda表达式
     */
    public class Demo01 {
        public static void main(String[] args) {
         /* Function<String,String> function= new Function<String,String>(){
    
              @Override
              public String apply(String str) {
                  return str;
              }
          };*/
    
            Function<String,String> function=  (str)->{return str;};
            System.out.println(function.apply("abc"));
        }
    }
    

    Predicate 断定型接口:只有一个传入参数,返回值只能是布尔值

    package com.mjh.function;
    
    import java.util.function.Predicate;
    
    /**
     * Predicate断定型接口  只有一个传入参数,返回值只能是布尔值
     */
    public class Demo02 {
        public static void main(String[] args) {
           /* Predicate<String> predicate = new Predicate<String>() {
                @Override
                public boolean test(String s) {
                    return s.isEmpty();
                }
            };*/
    
            Predicate<String> predicate=(s)->{ return s.isEmpty();};
    
            System.out.println(predicate.test("aaa"));
        }
    }
    

    Consumer 消费型接口:只有一个传入参数,没有返回值

    package com.mjh.function;
    
    import java.util.function.Consumer;
    
    /**
     *  Consumer  消费型接口  只有传入参数,,没有返回值
     */
    public class Demo03 {
        public static void main(String[] args) {
           /* Consumer<String> consumer = new Consumer<String>() {
                @Override
                public void accept(String s) {
                    System.out.println(s);
                }
            };*/
            Consumer<String> consumer =(s)->{
                System.out.println(s);
            };
    
            consumer.accept("ccccgfd");
        }
    }
    

    Suplier 供给型接口:没有参数,只有返回值

    package com.mjh.function;
    
    import java.util.function.Supplier;
    
    public class Demo04 {
        public static void main(String[] args) {
          /* Supplier<String> supplier = new Supplier<String>() {
                @Override
                public String  get() {
                    System.out.println("get()");
                    return "1024";
                }
            };
    */
            Supplier<String> supplier =()->{return "1024";};
                    System.out.println(supplier.get());
        }
    }
    

    作用:

    简化编程,提高效率

    12.Stream 流式计算

    package com.mjh.stream;
    
    import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
    
    import java.lang.reflect.Array;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    /**
     *题目要求:一分钟内完成此题,只能用一行代码实现!
     * 现在5个用户,筛选:
     * 1.ID必须是偶数
     * 2.年龄必须大于23岁
     * 3.用户转为大写字母
     * 4.用户名字倒着排序
     * 5.只输出一个用户
     */
    public class StreamTest {
        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(6,"e",25);
            User u6 =new User(8,"f",28);
            //集合就是存储
           List<User> list= Arrays.asList(u1,u2,u3,u4,u5,u6);
    
           //计算交给Steam流
            // lambda表达式,链式编程,函数式接口,Stream流式计算
            list.stream()
                    .filter(u->{return u.getId()%2==0;})
                    .filter(u->{return u.getAge()>23;})
                    .map(u->{return u.getName().toUpperCase();})
                    .sorted((uu1,uu2)->{return uu2.compareTo(uu1);})
                    .limit(1)
                    .forEach(System.out::println);
    
    
        }
    }
    

    13 .ForkJoin

    什么ForkJoin

    使用场景:并行执行任务,提高效率,大数据量!

    大数据:Map Reduce(把大任务拆分成小任务)

    ForkJoin 特点

    工作窃取

    这里面维护都是双端队列

    14.异步回调

    Future 设计的初衷:对将来的某个事件的结果进行建模

    package com.mjh.future;
    
    import java.util.concurrent.CompletableFuture;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.TimeUnit;
    
    /**  异步回调  CompletableFuture/Ajax
     * 异步执行
     * 成功回调
     * 失败回调
     */
    public class Demo {
        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()+"runAsync=>Void");
            });
            System.out.println("aaaaa");
            completableFuture.get();//阻塞获取执行结果
            */
    
            //有返回值的supplyAsync  异步回调
            //ajax,  成功和失败的回调
            //返回的是错误的信息
    
            CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
                System.out.println(Thread.currentThread().getName()+" supplyAsync=>Integer");
    
                int i=10/0;
                return 1024;
            });
    
            System.out.println(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 404;//可以获取到的错误的返回结果
                    }).get());
    
        }
    }
    
  • 相关阅读:
    Asp.net Treeview 客户端选中效果实现 (初级)
    MYSQL生成日历表,通常在做报表的时候需要用来生成一个临时表,用来左连接等。
    写了一个抽奖类,感觉还不错,可以适合各种变化
    将系统的内部类:HttpValueCollection 移到自己的系统中,使其能方便的解析id=1&name=张三&sex=男这样的字符串参数 querystring
    指定某个文件的创建 修改 访问时间
    Reqeust["keyname"] 的读取顺序
    pku1463 Strategic game
    pku1947 Rebuilding Roads
    pku1848 Tree
    pku1056 IMMEDIATE DECODABILITY
  • 原文地址:https://www.cnblogs.com/mjjh/p/13756432.html
Copyright © 2011-2022 走看看