java学习

JVM

多线程与高并发

23中设计模式

强大的Stream流

java NIO

JVM学习

三个阶段:

1、加载阶段

2、链接阶段(

  验证:保证被加载类的正确性,文件格式检验、元数据检验、字节码检验(CA FE BA BE)、符号引用检验

  准备:为类的变量分配内存且设置该变量的默认值,static修饰常量在编译时被分配了

  解析:编译器自动收集类中所有变量的赋值和静态代码块中的语句生成<clinit>()方法并执行。一个类执<clint>方法时在多线程环境下要保证同步加锁

3、初始化过程

 bootstrap:引导类加载器

ExtClassLoader:扩展类加载器

AppClassLoader:系统类加载器

双亲委派

 

 AppClassLoader类的加载器是BootStrap, AppClassLoader的父类是BootStrap加载器。

 

 

 

 

 jvm中启动参数

-Xms6G -Xmx6G:堆内存初始大小、最大大小

-XX:NewRatio=2 老年代与新生代比例,默认2

-XX:SurvivorRatio=8 :新生代中Eden与Survivor0、Survivor1的分配比例大小为8:1:1

 

 

多线程与高并发

进程:

线程:进程中最小的执行单元。

纤程:

线程状态:

 

 

 

 

 

synchronized关键字

♥当在方法上使用时锁为当前对象;当静态方法使用时锁为T.class,即类.class

    public  synchronized static void println(){
        try {
            System.out.println("线程方法执行。。");
            Thread.sleep(6000);

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

 

♥可重入

当同个对象中synchronized m1()方法调用synchronized m2()方法时,允许执行不会产生死锁。当子类中同步方法调用父类中的同步方法时,此时锁的是当前对象,两者的为同一把锁。

♥异常跟锁

出现异常且未处理,锁将会释放,会造成乱入。

♥锁底层实现

偏向锁(当有竞争时升级为自旋锁)

自旋锁(自旋10次后升级为重量级锁)

重量级锁-OS

执行时间短且线程数少,用自旋;执行时间长且线程数多,用系统锁

♥volatile

保证线程可见性,禁止指令重排序(单例模式)

♥CAS操作(无锁优化、自旋)

AtomicInteger类似Atomic开头的类全是自旋锁。
CAS(V,Expected,NewValue)V:当前值,Expected:期望值 ,NewValue:新的值;当前值和期望值相同时,认定为该值没有改变可以直接修改,否则将进行重试。
其中有Unsafe()类
ABA问题:加版本号

♥分段锁(LongAdder)

内部存在一个数组,将多个线程结果分布在数组中,最终将数组中的所有结果相加。

♥ReentrantLock和CountDownLatch

        /**ReentrantLock
         * 与synchronized相比,ReentrantLock为CAS且功能强大
         */
        ReentrantLock lock = new ReentrantLock(true);//是否为公平锁
        lock.isFair();//获取是否公平
        try {
            lock.lock();//上锁
        }finally {
            lock.unlock();//解锁
        }
        boolean hasLock = lock.tryLock(2, TimeUnit.SECONDS);//等待2s内尝试拿到锁,不会产生死锁
        /**CountDownLatch
         * 门栓,可以等待线程的结束
         */
        CountDownLatch latch = new CountDownLatch(100);//门栓
        latch.countDown();//数量减1
        latch.await();//等待在,在其他线程中数量减为0后等待结束

 ♥读写锁

//适用于频繁读操作,少量写操作。
        ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
        Lock readLock = lock.readLock();
        Lock writeLock = lock.writeLock();
        writeLock.lock();//保证仅有一个写操作
        readLock.lock();//保证多个读操作同事执行,但是有写操作时禁止读操作

 

♥Semaphore,限流

        //信号灯,Semaphore参数为可以允许最大的线程数。可以用来做限流
        Semaphore semaphore = new Semaphore(1);
        new Thread(()->{
            try {
                semaphore.acquire();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                semaphore.release();
            }
        }).start();
    }

 

♥线程之间数据通信Exchanger

        Exchanger<String> srtingExchanger = new Exchanger<>();
        new Thread(()->{
            try {
                System.out.println("1:"+srtingExchanger.exchange("this is thread1"));
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
            }
        }).start();

        new Thread(()->{
            try {
                System.out.println("2:"+srtingExchanger.exchange("this is thread2"));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();

 

注:该方法只允许2线程交换,但是可以有多个线程同时exchange,满足两个则交换,否则将会阻塞。

 ♥LockSupport

        Thread t1 = new Thread(() -> {
            try {
                System.out.println("开始");
                //阻塞线程,类似wait()
                LockSupport.park();
                System.out.println("结束");
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        t1.start();
        Thread.sleep(10000);
        //继续线程,类似notify()
        LockSupport.unpark(t1);

 

23中设计模式

创建者模式:

    工厂模式

    原型模式

创建者模式:

    建造者模式

结构型模式:

     代理模式

    适配器模式

    装饰者模式

    桥接模式

    外观模式

    组合模式

    享元模式

行为性模式:

    策略模式

    观察者模式

工厂模式:

一、简单工厂模式

角色:工厂、接口、实现接口的具体类。

内容:通过工厂传入一个参数,返回不同的实例。

可以使用配置文件加载对应实例到容器中

1、配置文件beanName.properties:

myTest=bean.pojo

2、工厂类:

public class Factory {
    //容器,存储初始化实例
    private static HashMap<String, pojo> map = new HashMap<String, pojo>();
    //加载配置文件,反射其对应实例
    static {
        Properties properties = new Properties();
        InputStream beanName = Factory.class.getClassLoader().getResourceAsStream("beanName.properties");
        try {
            properties.load(beanName);
            for (Object key : properties.keySet()) {
                Class<?> aClass = Class.forName(properties.getProperty((String) key));
                pojo pojo = (pojo) aClass.newInstance();
                map.put((String) key, pojo);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //从容器中获取对应的实例
    public static pojo getTest(String classNmae) {
        return map.get(classNmae);
    }
}

 

 

3、客户端:

    //从容器中获取对应的实例
    public static pojo getTest(String classNmae) {
        return map.get(classNmae);
    }

二、工厂方法模式

 角色:工厂接口、工厂实例、类接口、实现接口的具体类。

内容:客户通过传入不同的工厂,返回不同的实例。

 

 三、抽象工厂模式

角色:工厂接口、工厂实例、抽象的类、具体的类

内容:客户调用不同的工厂,可以返回对应的类群。

原型模式:

 浅克隆:实现Cloneable接口中的clone()方法,对非基本类型属性,仍指向原有属性所指向对象的内存地址

 深克隆:

建造模式:

produce文件(省略setter,getter等等):

public class Produce {
    private  String a;
    private  String b;
    private  String c;
    private  String d;
}

 

     方式一: 该方式分为 :产品Produce,建造者(抽象)Bulider,建造者(具体)Worker,♠指挥者 Director

注:由具体实现抽象,在具体中可以为produce中参数的赋值等操作,但是此时不调用不会赋值,只有通过指挥者的方法或者有参构造器进行对抽象方法的调用。

最后测试时为指挥者传入具体的建造者,并且调用获得produce

建造者(抽象):

public abstract class Builder {
    public abstract void setAA();
    public abstract void setBB();
    public abstract void setCC();
    public abstract void setDD();
    public  abstract  Produce getPeoduct();
}
抽象者(具体):
public class Worker extends  Builder {
    //由具体建造者的无参构造方法new产品
    private  Produce p;
    public Worker() {p=new Produce();}
    @Override
    public void setAA() {p.setA("注入A");}
    @Override
    public void setBB() {p.setB("注入b");}
    @Override
    public void setCC() { p.setC("注入c"); }
    @Override
    public void setDD() { p.setD("注入D"); }
    @Override
    public Produce getPeoduct() {return p;}
}
指挥者(可以合并到抽象类中):
public class Director {
    public Produce getProduct(Builder builder){
        builder.setAA();
        builder.setBB();
        builder.setCC();
        builder.setDD();

        return builder.getPeoduct();
    }
}
测试:
Director director = new Director();
Produce p = director.getProduct(new Worker());
System.out.println(p.toString());

 

方式二:给方式将指挥者角色的功能赋予用户
建造者(抽象):
public abstract class Builder {
    public abstract Builder setAA(String msg);
    public abstract Builder setBB(String msg);
    public abstract Builder setCC(String msg);
    public abstract Builder setDD(String msg);

    public  abstract  Produce getPeoduct();
}
抽象者(具体):依旧new对象,并且在这里对对象中属性赋值操作是返回的还是抽象者本身,最终要通过getProduct()方法实现获取对象
public class Worker extends Builder {
    private  Produce p;
    public Worker() {p=new Produce();}
    @Override
    public Builder setAA(String msg) {p.setA(msg);return this;}
    @Override
    public Builder setBB(String msg) {p.setB(msg);return this;}
    @Override
    public Builder setCC(String msg) {p.setC(msg);return this;}
    @Override
    public Builder setDD(String msg) {p.setD(msg);return this;}
    @Override
    public demo2.Produce getPeoduct() {return p;}
}

 

测试:
Worker worker = new Worker();
Produce peoduct = worker.setAA("lala").setBB("hahah").getPeoduct();//通过链式编程实现对属性赋值
System.out.println(peoduct.toString());

 

 ♥代理模式

一、静态代理

真正执行的方法,被代理类的方法中调用,调用代理类方法则会调用真正的方法。

二、JDK动态代理(本质上是底层代码生成一个在内存中的类,去调用真正的方法)

        //为了获取加载器和getInterfaces
        pojo pojo = new pojo();
        //本质是一个实现接口的类,该类代理的pojo中的所有方法
        Peoper proxr = (Peoper) Proxy.newProxyInstance(pojo.getClass().getClassLoader(), pojo.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            /**
             * Object proxy:代理对象。
             * Method method:调用对应方法的封装method对象
             * Object[] args:调用方法的实际参数
             */
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("增加对应的逻辑处理!");
                Object invoke = method.invoke(pojo, args);
                return invoke;
            }
        });
        System.out.println("do返回:" + proxr.doing("do do  do"));
        proxr.reading("wgy", "java");
        System.out.println("代理类Class:"+proxr.getClass());

 

 使用arthas解析代理类Class:com.sun.proxy.$Proxy0,启动arthas-boot.jar后选择对应的进程,然后输入jad com.sun.proxy.$Proxy0

下载 | arthas (aliyun.com)

解析之后的真正代理类:

public final class $Proxy0 extends Proxy implements Peoper {
    private static Method m4;
    public $Proxy0(InvocationHandler invocationHandler) {
        super(invocationHandler);
    }
    static {
            m4 = Class.forName("bean.Peoper").getMethod("doing", Class.forName("java.lang.String"));
    }
    public final String doing(String string) {
        try {
            return (String)this.h.invoke(this, m4, new Object[]{string});
        }
        catch (Error | RuntimeException throwable) {
            throw throwable;
        }
        catch (Throwable throwable) {
            throw new UndeclaredThrowableException(throwable);
        }
    }
}

 

 三、CGLIB动态代理

与JDK代理区别: CGLIB可以代理没有实现接口的类,而JDK代理则无法实现。

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>

 

        //为了获取加载器和getInterfaces
        pojo pojo = new pojo();
        //创建Enhancer对象,类似JDK中的Proxy
        Enhancer enhancer = new Enhancer();
        //设置父类的字节码对象
        enhancer.setSuperclass(pojo.class);
        //设置回调函数
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("执行操作前");
                Object invoke = method.invoke(pojo, objects);
                System.out.println("执行操作后");
                return invoke;
            }
        });
        pojo pojoProxy = (pojo) enhancer.create();
        System.out.println(pojoProxy.doing("wgy"));

 

 ♥适配器模式

 

一、类适配器:

实现适配者的接口,继承目标类。实现适配者中方法且在方法中调用父类方法。需要开发人员明确组件中接口。本质上就是在目标对象外套一层。

二、对象适配器:

 

 与类适配器相比,只是不继承目标对象需要在外部传入一个目标对象。本质上就是在目标对象外套一层。

 

 ♥装饰者模式

 

 

 

抽象装饰者继承抽象构建,在具体装饰者中传入旧具体构建对其装饰后返回新具体构建。

具体的特征:装饰者中会聚合一个父类,即Garnish中有FastFood。

 

 

 ♥外观模式(门面模式-迪米特法则)


 ♥组合模式


 ♥享元模式

 

 

类似单例模式,把多个重复的对象共享同一个。


桥接模式(多对多的情况下考虑使用)
桥梁模式的作用主要是将抽象和实现分离,抽象类与接口的实现分离,抽象的实体与实体的接口特性进行分离。

 

 

策略模式

示例代码:

 

 优缺点:

 ♥观察者模式

该模式下包含角色:
  1、抽象主题角色(Observable)
  2、具体主题角色
  3、观察者接口角色(Observer)
  4、具体的观察者角色
具体代码:
  1、主题角色(继承java类Observable)
public class MyObserverable extends Observable {
    public void excute() {
        //设置具体主题中发生变化
        setChanged();
    }
}

 

  2、观察者角色(实现Observer接口,重写update()方法)
public class MyObserver implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("订阅通知收到消息!");
    }
}

 

  3、客户端
public class Client {
    public static void main(String[] args) {
        //创建具体主题。
        MyObserverable myObserverable = new MyObserverable();
        //创建观察者
        MyObserver myObserver = new MyObserver();
        //观察者订阅主题
        myObserverable.addObserver(myObserver);
        for (int i = 0; i < 5; i++) {
            //在具体主题中设置主题发生变化。
            myObserverable.excute();
            //在具体主题中通知观察者,当主题发生变化时执行update()方法,若没有发生变化则不执行。
            myObserverable.notifyObservers();
        }

    }
}



强大的Stream流

 

1、获取流

List<String> list = new ArrayList<>();
Stream<String> stream = list.stream(); //获取一个顺序流
Stream<String> parallelStream = list.parallelStream(); //获取一个并行流
注:顺序流是单线程运行,并行流为多线程执行;验证如下代码:
        ArrayList<String> list = new ArrayList<>();
        list.add("1,2,3,4,5,6");
        list.add("a,b");
        list.add("g,h,i,j,k,l");
        list.add("p,k,s");
        //顺序流
        list.parallelStream().peek(o -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).forEach(a -> System.out.println(a));
        //并行流
        list.parallelStream().peek(o -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).forEach(a -> System.out.println(a));

2、中间操作

fliter
Stream<String> stringStream = list.stream().filter(a -> a.length() > 4);//只有长度大于4输出
limit
Stream<String> limit = list.stream().limit(6);//取前6个值

 

peek
list.stream().peek(o -> System.out.println(++o)).forEach(a -> System.out.println(a));//消费对其中的数据可以处理

 

skip:跳过n个值
sorted:排序
count:个数
reduce:规约
Integer integer = list.stream().reduce((a, b) -> {
   System.out.println(a + "   " + b);
   return a + b;
}).get();

 

map/flatMap
list.stream().map(a->a.replaceAll(",","")).forEach(a-> System.out.println(a));
list.stream().flatMap(a-> Arrays.stream(a.split(","))).forEach(a-> System.out.println(a));

 

3、Collectors工具库

toMap、toList、toSet:转对应集合
Map<Integer, String> collect = list.stream().collect(Collectors.toMap(a -> a.hashCode(), a -> a));
collect.forEach((a,b)-> System.out.println(a+":"+b));

 

groupingBy:分组
Map<Integer, List<String>> collect2 = list.parallelStream().collect(Collectors.groupingBy(a -> a.length()));
collect2.forEach((a,b)->{
System.out.println("wgy:"+a);
b.forEach(c-> System.out.println(c));
});

 

partitioningBy:分区,只能分为TRUE、FALSE
Map<Boolean, List<String>> collect3 = list.stream().collect(Collectors.partitioningBy(a -> a.length() > 5));
collect3.forEach((a, b) -> {
System.out.println("wgy:" + a);
b.forEach(c -> System.out.println(c));
});

 

 mapping:映射
List<Integer> collect4 = list.stream().collect(Collectors.mapping(a -> a.length(), Collectors.toList()));
System.out.println(collect4);

 

joining:连接字符
reducing:规约
counting:计数





java NIO(同步非阻塞)

Bio 同步阻塞,面向流
Aio 异步非阻塞
















posted @ 2021-11-27 15:21  王啦啦  阅读(46)  评论(0)    收藏  举报