欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

面向函数式编程

程序员文章站 2022-05-08 09:16:05
...

面向函数式编程@FunctionalInterface

  • 1:面向函数式编程四大点:

    /**
     *   面向函数式编程
     * 1 拷贝方法的后面小括号(有参数就带参数),写死右箭头,落地大括号(内写方法的实现)---lambda表达式
     * 2 本质就是接口中只有一个方法时,jdk8 会自动在接口上默认@FunctionalInterface
     * 3 default 就是在接口定义方法上,实现了方法 可以允许存在多个default方法
     * 4 static  静态代码块,可以运行存在多个default方法`
     */
    
eg:
public static void main(String[] args) {
/*        匿名内部类方式调用无参数无返回值的foo接口的方法·
        Foo foo1=new Foo() {
            @Override
            public void sayhello() {
                System.out.println("我要sayhello--匿名内部类方式调用无参数无返回值的foo接口的方法");
            }
        };
        foo1.sayhello();
*/
/*       使用lambda表达式调用无参数无返回值的foo接口的方法
       使用:拷贝小括号,写死右箭头,落地大括号+表达式
        Foo foo2=()->{System.out.println("我要sayhello--使用lambda表达式调用无参数无返回值的foo接口的方法");};
        foo2.sayhello();
*/
//        使用lambda表达式调用有参数有返回值的foo接口的方法
        Foo foo3=(int x,int y)->{System.out.println(" 使用lambda表达式调用有参数有返回值的foo接口的方法:");return x+y;};
        System.out.println(foo3.add(3, 4));
    //    使用静态代码块或者default的接口方法时,只用接口方法. 就可以了
        System.out.println(Foo.div(10, 5));
}
  • 2:Collection 和Collections

    • Collection 是一个集合接口,提供了对集合对象进行基本操作的通用接口方法
    • Collections 是一个包装类。它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,服务于Java的Collection框架。
  • 3:ArrayList的使用错误实例

    • 出错的代码及其异常: //异常: java.util.ConcurrentModificationException

      //异常  java.util.ConcurrentModificationException
      public static void main(String[] args) {
          	//使用了Arraylist是一种线程不安全的方法
              List<Object> list = new ArrayList<>();
      
              for (int i=0;i<30;i++){
                  new Thread(()->{
                      //使用uuid来随机生成,然后转换为字符串,并且将字符串分割取出0-8位
                      list.add(UUID.randomUUID().toString().substring(0,8));
                      System.out.println(list);
                  },String.valueOf(i)).start();
              }
          }
      

      解决异常方法

         List<Object> list = new ArrayList<>();    (线程不安全)改为
      (1)List<Object> list = new Vector<>();  本质add方法使用了synchronized,进行了上锁,不建议 (线程安全)
      (2)List<Object> list = Collections.synchronizedList(new ArrayList<>());  使用了Collections工具类
      (3)List<Object> list =new CopyOnWriteArrayList<>();  具有内存占用问题,并且有数据一致性问题。CopyOnWrite容器只能保证数据的最终一致性,不能保证数据的实时一致性。所以如果你希望写入的的数据,马上能读到,请不要使用CopyOnWrite容器。在开辟一个length+1的数组,并且把最新的数据放入数组的最后,并且将对老数组的索引转换到新数组上
      /**
      copyonurite容器即写时复制的容器。往一个容器添加元素的时候,不直接往当前容器object[]添加,而是先将当前容器object[]进行copy,复制出一个新的容器bject[] newElements,然后新的容器object[] newElements里添加元素,添加完元素之后,再将原容器的引用指向新的容器setArray(newElements);。这样做的好处是可以为copyonurite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素,所以copyonwrite也是一种读写分离的思想,读和写不同的容器
      */
      
    • 八锁情况(自定义的)

       * 1 标准访问。俩个同步代码块,一部手机,俩个用户,先发短信还是邮件               -------邮件
       * 2 暂停3秒再发邮件,1部手机,俩个用户,先发短信还是邮件                       -------邮件
       * 3 一个普通方法,一个同步代码块,1部手机,俩个用户,先发普通方法还是邮件         -------普通方法
       * 4 2部手机,先发短信还是邮件                                              -------短信
       * 5 俩个静态代码块,一部手机,俩个用户,先发短信还是邮件                        -------邮件
       * 6 俩个静态代码块,2部手机,俩个用户,先发短信还是邮件                         -------邮件
       * 7 一个静态代码块,一个同步代码块,1部手机,俩个用户,先发普通方法还是邮件        -------短信
       * 8 一个静态代码块,一个同步代码块,2部手机,俩个用户,先发普通方法还是邮件        -------短信
      

      详情

      synchronize锁的是对象,创建出来的对象  eg:phone1,phone2
      static synchronize 锁的是创建这个对象的模板,为整个Class类  eg:Phone
      同步方法和普通方法,等于俩道门,俩把锁,不影响
      
    • 多线程的相互调用资源类,防止过多调用,过着过少调用(生产与消费)

       * 题目:现在两个线程,可以操作初始值为零的一个变量,
       * -实现一个线程对该变量加,一个线程对该变量减,
       * 实现交替,来10,变量初始值为零。
      
    • 解决方案:

      • 1 高聚低合前提下,线程操作资源类
      • 2 判断/干活/通知
      • 3 防止虚假唤醒,所以每次苏醒都得判断(用while进行判断,一旦不该苏醒的时候苏醒,就沉入睡眠)
    eg:
    //空调类--资源类
    public class Aircondition {
    
    //    度数
        private int number=0;
    
    //    空调-1度
        public synchronized void decrement() throws Exception{
    //      判断,防止虚假唤醒,所以每次苏醒都得判断
            while(number!=1){
                this.wait();
            }
    //        干活
                number--;
                System.out.println(Thread.currentThread().getName()+"当前的number-1,number=:"+number);
    //        通知(唤醒其他线程)
                this.notify();
        }
    
    //    空调+1度
        public synchronized void increment() throws Exception{
            //判断,防止虚假唤醒,所以每次苏醒都得判断
            while(number!=0){
                this.wait();
            }
            //干活
                number++;
                System.out.println(Thread.currentThread().getName()+"当前的number+1,number=:"+number);
            //通知(唤醒其他线程)
            this.notify();
        }
    }
    
    • 遇到多个线程按照固定顺序来进行运行,例如A->B->C->A····

      • 应当在资源类上精准配置钥匙,即标示位

        public class ShareData {
            private Lock lock=new ReentrantLock();
            private Condition c1 = lock.newCondition();
            private Condition c2 = lock.newCondition();
            private Condition c3 = lock.newCondition();
            private int number=1;//A:1 B:2 C:3
        
            public void doA() throws InterruptedException {
                lock.lock();
                try{
        //           判断
                    while(number!=1){
                       c1.await();
                    }
        //           执行
                    System.out.println("我是A,我打印了5次");
        //           通知
                    number=2;
                    //唤醒第二个线程
                    c2.signal();
                }catch(Exception e){
                    e.printStackTrace();
                }finally {
                    lock.unlock();
                }
            }
            public void doB() throws InterruptedException {
                lock.lock();
                try{
        //           判断
                    while(number!=2){
                        c2.await();
                    }
        //           执行
                    System.out.println("我是B,我打印了10次");
        //           通知
                    number=3;
                    c3.signal();
                }catch(Exception e){
                    e.printStackTrace();
                }finally {
                    lock.unlock();
                }
            }
            public void doC() throws InterruptedException {
                lock.lock();
                try{
        //           判断
                    while(number!=3){
                        c3.await();
                    }
        //           执行
                    System.out.println("我是C,我打印了15次");
        //           通知
                    number=1;
                    c1.signal();
                }catch(Exception e){
                    e.printStackTrace();
                }finally {
                    lock.unlock();
                }
            }
        }
        
        配置多把钥匙,来上锁
        private Condition c1 = lock.newCondition();
        private Condition c2 = lock.newCondition();
        private Condition c3 = lock.newCondition();
        
    • 可获取函数的返回值,(异步操作)

      主线程
      public class CallableDemo {
      
          public static void main(String[] args) throws ExecutionException, InterruptedException {
      
              FutureTask<Integer> futureTask = new FutureTask(new MyThread());
      
      //       进入了方法
              new Thread(futureTask,"A").start();
      
      //       获取任务执行结果,任务结束之前会阻塞
              Integer result = futureTask.get();
              System.out.println(result);
          }
      }
      
      资源类,需要继承Callable<>接口
      public class MyThread implements Callable<Integer>{
      
          @Override
          public Integer call() throws Exception {
              System.out.println("********call in back on");
              return 1024;
          }
      }
      

      面向函数式编程

      未完待续----------------

相关标签: 多线程