JUC笔记(2)

14、四大函数式接口

(1)函数式接口

@FunctionalInterface
public interface Function<T, R> {

    /**
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);
}
package com.gykj;

import java.util.function.Function;

/**
 * Function 函数式接口,有一个数日参数,有一个输出
 * 只要是 函数式解耦,可以用lamnda表达式简化
 */

public class FunctionDemo {

    public static void main(String[] args) {
        Function function=new Function<String,String>(){
            @Override
            public String apply(String s) {
                return s;
            }
        };
        Function function1 = (s)->{return  s;};

        System.out.println(function.apply("sfaf"));
    }
}

(2)断定式接口

@FunctionalInterface
public interface Predicate<T> {

    /**
     * Evaluates this predicate on the given argument.
     *
     * @param t the input argument
     * @return {@code true} if the input argument matches the predicate,
     * otherwise {@code false}
     */
    boolean test(T t);
}
package com.gykj;

import java.util.function.Predicate;

/**
 * 断定式接口:有一个输入参数,返回值只能是布尔值!
 */
public class PredicateDemo {
    public static void main(String[] args) {
        Predicate<String> predicate = new Predicate<String>(){
            @Override
            public boolean test(String o) {
                return o.isEmpty();
            }
        };
        Predicate<String> predicate1 = (s)->{return s.isEmpty();};
        System.out.println(predicate1.test("123"));
    }
}

(3)消费型接口

@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);
}
package com.gykj;

import java.util.function.Consumer;

/**
 * 消费型解耦:只有输入,没有返回值
 */
public class ProductDemo {
    public static void main(String[] args) {
        Consumer<String> consumer = new Consumer<String>(){
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        Consumer<String> consumer1 = (s)->{
            System.out.println("aaavvvv");;};
        consumer1.accept("aaaaa");
    }
}

(4)供给型接口

@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}
package com.gykj;

import org.omg.CORBA.INTERNAL;

import java.util.function.Supplier;
//供给型接口,没有输出,只有返回值

public class SupplierDemo {
    public static void main(String[] args) {
        Supplier supplier = new Supplier<Integer>(){
            @Override
            public Integer get() {
                System.out.println("get()");
                return 1024;
            }
        };
        Supplier supplier1 = ()->{
            System.out.println("get()");
            return 1024;
        };
        System.out.println(supplier1.get());
    }
}

15、stream流式计算

16、forkjoin

大任务拆分成小任务

特点:工作窃取

package com.gykj;

import java.util.concurrent.RecursiveTask;

/**
 * 求和计算的任务
 * 如何使用forkjoin
 *      forkjoinPool通过他来执行
 *      计算任务forkjoinPool.executor(ForkJoinTask task)
 *      计算类要继承ForkJoinTask
 */

public class ForkJoinDemo extends RecursiveTask<Long> {

    private Long start;
    private Long end;

    //临界值
    private Long temp = 100000L;

    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 {
            //forkjoin递归
            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();
        }
    }
}
package com.gykj;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;

public class ForkTest {
    public static void main(String[] args)  throws ExecutionException,InterruptedException {
//        test1();//sum=500000000500000000, time=23716
//        test2();//sum=500000000500000000, time=16125
        test3();//sum=500000000500000000, time=1396


    }
    public static void test1(){
        Long sum = 0L;
        long start = System.currentTimeMillis();
        for(Long i = 1L;i<=10_0000_0000;i++){
            sum+=i;
        }
        long end = System.currentTimeMillis();
        System.out.println("sum="+sum+", time="+(end-start));
    }

    public static void test2() throws ExecutionException,InterruptedException {
//        Long sum = 0L;
        long start = System.currentTimeMillis();
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        ForkJoinTask<Long> task = new ForkJoinDemo(0L,10_0000_0000L);
        ForkJoinTask<Long> submit = forkJoinPool.submit(task);//提交任务
        Long sum = submit.get();
        long end = System.currentTimeMillis();
        System.out.println("sum="+sum+", time="+(end-start));
    }
    public static void test3(){
        long start = System.currentTimeMillis();
        //Stream并行流
        long sum = LongStream.rangeClosed(0L,10_0000_0000L).parallel().reduce(0,Long::sum);
        long end = System.currentTimeMillis();
        System.out.println("sum="+sum+", time="+(end-start));
    }
}

17 异步回调

package com.gykj;

import org.omg.PortableInterceptor.INACTIVE;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * 异步调用:CompletableFuture
 *  异步执行
 *  成功回调
 *  失败回调
 */
public class FutrueDemo {
    public static void main(String[] args) throws ExecutionException,InterruptedException {
        //没有返回值的runAsSync 异步毁掉
        CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(()->{
            try {
                TimeUnit.SECONDS.sleep(2);
            }catch (InterruptedException e){
                e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"runAdSync=>void");
        });
        System.out.println("1111");
        completableFuture.get();//获取阻塞执行结果
        //有返回值的supplyAsync 异步回调
        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);
        }).exceptionally((e)->{
            System.out.println(e.getMessage());
            return 233;//可以获取错误的返回信息
        }).get());

    }




}

18.volatile

(1)保证可见性

package com.gykj;

import java.util.concurrent.TimeUnit;

public class JMMDemo {
    private volatile static int num = 0;

    public static void main(String[] args) {
        new Thread(()->{
            while (num==0){

            }
        }).start();
        try {
            TimeUnit.SECONDS.sleep(1);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        num = 1;
        System.out.println(num);
    }
}

(2)不保证原子性

package com.gykj;

public class JMMDemo2 {
    private volatile static int num = 0;
    public static void add(){
        num++;
    }

    public static void main(String[] args) {
        for (int i=1; i<=20;i++){
            new Thread(()->{
                for(int j=0;j<1000;j++){
                    add();
                }
            }).start();
        }

        while (Thread.activeCount()>2){
            Thread.yield();
        }
        System.out.println(Thread.currentThread()+"   "+num);
    }
}

如何在不使用lock和synchronized情况下保证正确

package com.gykj;

import java.util.concurrent.atomic.AtomicInteger;

public class JMMDemo2 {
    private volatile static AtomicInteger num = new AtomicInteger();
    public static void add(){
//        num++;
        num.getAndIncrement();
    }

    public static void main(String[] args) {
        for (int i=1; i<=20;i++){
            new Thread(()->{
                for(int j=0;j<1000;j++){
                    add();
                }
            }).start();
        }

        while (Thread.activeCount()>2){
            Thread.yield();
        }
        System.out.println(Thread.currentThread()+"   "+num);
    }
}

19、单例模式

(1)饿汉式模式

package com.gykj.single;

//饿汉式单例
public class Hungry {
    //弊端,可能会浪费时间
    private byte[] data1 = new byte[1024*1024];
    private byte[] data2 = new byte[1024*1024];
    private byte[] data3 = new byte[1024*1024];
    private byte[] data4 = new byte[1024*1024];
    
    private Hungry{}
    
    private final static Hungry HUNGRY = new Hungry();
    
    public final static Hungry getInstance(){
        return HUNGRY;
    }
}

(2)懒汉式模式

package com.gykj.single;

public class LazyMan {
    private LazyMan(){
        System.out.println(Thread.currentThread().getName()+"ok");
    }
    private static LazyMan lazyMan;

    //双重检测锁模式  懒汉式单例  DCL懒汉式
    private static LazyMan getInstance(){
        if(lazyMan == null){
            synchronized (LazyMan.class){
                if(lazyMan == null){
                    lazyMan = new LazyMan();
                    /**
                     * new LazyMan 不是一个原子操作
                     * 1.分配内存空间
                     * 2.执行构造方法,初始化对象
                     * 3.把这个对象指向这个空间
                     *
                     * 123
                     * 132   //此时lazyMan还没有完成构造
                     */
                }
            }
        }
        return lazyMan;
    }

    public static void main(String[] args) {
        for (int i=0;i<10;i++){
            new Thread(()->{
                LazyMan.getInstance();
            }).start();
        }
    }
}

(3)内部类

package com.gykj.single;


public class Holder {
    private Holder(){}
    
    private static Holder getInstance(){
        return InnerClass.HOLDER;
    }
    public static class InnerClass{
        private static final Holder HOLDER = new Holder();
    }
}

通过静态内部类的方式实现单例模式是线程安全的,同时静态内部类不会在Singleton类加载时就加载,而是在调用getInstance()方法时才进行加载,达到了懒加载的效果。

似乎静态内部类看起来已经是最完美的方法了,其实不是,可能还存在反射攻击或者反序列化攻击。且看如下代码:

 

public static void main(String[] args) throws Exception {
    Singleton singleton = Singleton.getInstance();
    Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();
    constructor.setAccessible(true);
    Singleton newSingleton = constructor.newInstance();
    System.out.println(singleton == newSingleton);
}

(4)枚举

package com.gykj.single;

import org.omg.CORBA.PUBLIC_MEMBER;

public enum  EnumSingle {
    INSTANCE;
    
    public EnumSingle getInstance(){
        return INSTANCE;
    }
}

通过反编译,他的构造参数并不是无参,而是有参

20 CAS

package com.gykj;

import java.util.concurrent.atomic.AtomicInteger;

public class CASDemo {
    public static void main(String[] args) {
        AtomicInteger atomicInteger = new AtomicInteger(2021);

        System.out.println(atomicInteger.compareAndSet(2021,2022));
        System.out.println(atomicInteger.get());

        System.out.println(atomicInteger.compareAndSet(2021,2022));
        System.out.println(atomicInteger.get());

    }
}
//调用了unsafe方法   CAS是CPU的并发原语
public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }


//自旋锁
public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

        return var5;
    }

CAS:比较当前工作内存中的值和主内存中的值,如果这个值是期望的,那么则执行操作 ,如果不是就一直循环

缺点:

        循环会耗时

        一次性只能保证一个共享变量的原子性

        ABA问题

 21、原子问题

package com.gykj;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicStampedReference;

public class CASDemo2 {
    static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(1,1);

    public static void main(String[] args) {
        new Thread(()->{
            int stamp = atomicStampedReference.getStamp();
            System.out.println("a1=>"+stamp);

            try {
                TimeUnit.SECONDS.sleep(5);
            }catch (InterruptedException e){
                e.printStackTrace();
            }

            atomicStampedReference.compareAndSet(1,2,
                    atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1);
            System.out.println("a2=>"+atomicStampedReference.getStamp());

            atomicStampedReference.compareAndSet(2,1,
                    atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1);
            System.out.println("a3=>"+atomicStampedReference.getStamp());
        },"a").start();


        new Thread(()->{
            int stamp = atomicStampedReference.getStamp();//获得版本号
            System.out.println("b1=>"+stamp);

            try {
                TimeUnit.SECONDS.sleep(2);
            }catch (InterruptedException e){
                e.printStackTrace();
            }

            System.out.println(atomicStampedReference.compareAndSet(1,6, stamp,stamp+1));

            System.out.println("b2=>"+atomicStampedReference.getStamp());
        },"b").start();
    }
}

注:Integer使用了对象缓存机制,默认范围为-128-127,推荐使用静态工厂方法valueOf获取对象实例,而不是new,因为valueOf使用缓存,而new一定会创建新的对象分配新的内存空间

排查死锁问题

使用jps -l 定位进程号

使用jstack 进程号  找到死锁问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值