JUC并发编程总结(二)

点我跳转至JUC并发编程总结(一)

  • 前言:此总结更接近于使用和回顾juc内容。如果需要深入研究底层,请看源码或者官网文档。

函数接口、流式计算

四大函数式接口

  1. Predicate函数式接口,断言型,返回true/false
  2. Function函数式接口,函数型,有输入输出。
  3. Consumer函数式接口,消费型,有输入输出。
  4. Supplier函数式接口,供给型,无输入有输出。
  • Predicate,重写test方法。提供两种效果一样的实现方式。
     Predicate predicate =new Predicate<String>() {
         @Override
         public boolean test(String o) {
             return false;
         }
     };
     Predicate predicate1=(str)->{return false;};
     System.out.println(predicate.test("0"));
    
  • Function,重写apply方法。提供两种效果一样的实现方式。第一个是传入参数,第二个是返回值。
     Function function =new Function<Integer,String> (){
         @Override
         public String apply(Integer o) {
             return o+"";
         }
     };
     Function function1=(str)->{return str;};
     System.out.println(function1.apply(5));
    
  • Consumer,重写accept方法。提供两种效果一样的实现方式。
    Consumer consumer=new Consumer<String>() {
        @Override
        public void accept(String o) {
            System.out.println(o);
        }
    };
    Consumer consumer1 =(str)->{ System.out.println(str);};
    consumer1.accept("消费者接口被调用");
    
  • Supplier,重写get方法。提供两种效果一样的实现方式。
     Supplier supplier=new Supplier<Integer>() {
         @Override
         public Integer get() {
             return null;
         }
     };
     Supplier supplier1 =()->{System.out.println("接口被调用"); return "aaa";};
     System.out.println( supplier1.get());
    

流式计算stream

  • 流式计算常用于计算大的数据量,效率非常高。是常规计算效率的十倍。
  • 示例:
        public static void main(String[] args) {
            List<User> list =new ArrayList<>();
            for (int i = 0; i <6 ; i++) {
                User user=new User(i,i+"娃",i);
                list.add(user);
            }
            list.stream()
                    .filter(u->{return u.getId()%2==0;})
                    .filter(u->{return u.getAge()>2;})
                    .map(u->{return u.getName().replace("娃","wa");})
                    .sorted((uu1,uu2)->{return uu2.compareTo(uu1);})
                    .limit(1)
                    .forEach(System.out::println);
        }
    

Forkjoin

工作模型

在这里插入图片描述

注意事项

  • 使用
  1. 使用ForkJoinPool来执行分段任务。
  2. 计算任务forkJoinPool.submit(task)
  3. 计算类要继承ForkJoinTask,重新compute方法。
  • 示例 :分段计算任务。
    class ForkJoinDemo extends RecursiveTask<Long>{
        private Long temp =1000L;
        private Long start;
        private Long end;
    
        public ForkJoinDemo(Long start, Long end) {
            this.start = start;
            this.end = end;
        }
        @Override
        protected Long compute() {
           if (end-start<temp){
               Long sum=0L;
               for (Long i = start; i <=end ; i++) {
                   sum+=i;
               }
               return sum;
           }else {
               long middle=(start+end)/2;
               ForkJoinDemo task1=new ForkJoinDemo(start,middle);
               task1.fork();
               ForkJoinDemo task2=new ForkJoinDemo(middle+1,end);
               task2.fork();
               return task1.join()+task2.join();
           }
        }
    }
    
    public class Demo08Forkjoin {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            Long start = System.currentTimeMillis();
            //使用forkjoin
            ForkJoinPool forkJoinPool=new ForkJoinPool();
            ForkJoinTask task =new ForkJoinDemo(0L,10000000L);
            ForkJoinTask submit =forkJoinPool.submit(task);
            Long sum = (Long) submit.get();
    
            Long end = System.currentTimeMillis();
            System.out.println(end-start+":"+sum);
    
            Long start1 = System.currentTimeMillis();
            //不使用
            Long sum1=0L;
            for (Long i = 0L; i <=10000000L ; i++) {
                sum1+=i;
            }
            Long end1 = System.currentTimeMillis();
            System.out.println(end1-start1+":"+sum1);
        }
    }
    

异步

  • CompletableFuture和函数接口一样也提供了supplyAsync()/runAsync等方法。使用时选择正确的方法。
  • 像JS和Promise那样执行异步任务。
            CompletableFuture<Integer> completableFuture=CompletableFuture.supplyAsync(()->{
                try {
                    TimeUnit.SECONDS.sleep(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("异步任务执行完毕");
                return 500;
            });
            System.out.println("主线程任务");
            completableFuture.get();
    
           int a =  completableFuture.whenComplete((t,u)->{
                System.out.println("正确执行时返回结果:"+t);
                System.out.println("正确执行时返回结果:"+u);
            }).exceptionally((e)->{
                return  233;
            }).get();
           
           System.out.println(a);
    

JMM到单例模式

1. 对Volatile关键字的理解

  • volatile是java虚拟机提供的轻量级同步机制。
  1. 保证可见性
  2. 不保证原子性
  3. 禁止指令重排
  • 通知其他线程变量已经更改。

2. JMM:java内存模型

在这里插入图片描述
在这里插入图片描述

  • 保证可见性:
    在这里插入图片描述
  • 不保证原子性 :多个线程修改带有volatile关键字的变量时仍然会出问题。
  • 禁止指令重排 (了解更多请查看相关文档)
  1. 保证特定操作有序
  2. 保证变量内存可见性。

3. 彻底玩转单例模式

在这里插入图片描述

CAS:比较并交换

1. 理解CAS

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 缺点
  1. 循环耗时
  2. 一次保证一个共享变量原子性
  3. ABA问题
    在这里插入图片描述

2. 原子引用

在这里插入图片描述

各种锁

公平锁、非公平锁

  • 关键是能不能插队的问题
  • 可重入锁构造方法
    在这里插入图片描述

可重入锁(递归锁)

  • 得到大门锁,自然得到房间锁。
  • 注意sms里面调用了call()在这里插入图片描述

自旋锁

在这里插入图片描述

死锁问题排查方案

  1. 使用jps- a进行进程号定位:
    在这里插入图片描述
  2. 使用jstack 进程号进行定位
    在这里插入图片描述

AQS(AbstractQueuedSynchronizer)

  • 此类事锁的实现原理。

手动写一个锁。

public class Demo11AQS {
    public static void main(String[] args) throws InterruptedException {
        final Integer[] sum = {0};
        Lock lock =new MyLock();
        Thread[] a= new Thread[500];
        for (int j = 0; j <500 ; j++) {
          a[j] = new Thread(()->{
                lock.lock();
                sum[0]++;
                lock.unlock();
            });
          a[j].start();
        }
        for (Thread item:a){
            item.join();
        }
        System.out.println(sum[0]);
    }
   static void add(Integer a,Integer b){
        a=a+b;
   }
}

class MyLock implements Lock {

    private Sync sync =new Sync();

    @Override
    public void lock() {
        sync.acquire(1);
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {

    }

    @Override
    public boolean tryLock() {
        return false;
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return false;
    }

    @Override
    public void unlock() {
        sync.release(1);
    }

    @Override
    public Condition newCondition() {
        return null;
    }
    private class Sync extends AbstractQueuedSynchronizer{
        @Override
        protected boolean tryAcquire(int arg) {
            assert arg==1;
            if (compareAndSetState(0,1)){
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }
        @Override
        protected boolean tryRelease(int arg) {
            assert arg==1;
            if (! isHeldExclusively()) try {
                throw new IllegalAccessException();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }
        @Override
        protected boolean isHeldExclusively() {
            return getExclusiveOwnerThread()==Thread.currentThread();
        }
    }
}

Reference

  1. https://www.jianshu.com/p/c366c9238bb8
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值