JVM JUC

代码编程要求高内聚低耦合(我(线程)拿遥控器开(操作)空调(高内聚,空调被封装只有一个遥控开关) )

  1.线程     操作       资源类

JAVA Lambda表达式函数式接口

  1. 复制小括号    写死右箭头   落地大括号(函数式接口中只能有一个方法)

  2.  @FunctionalInterface

  3. default  可以定义多个

  4. static  可以是多个

package work;



@FunctionalInterface
interface Foo{
    
    public int run();
    
    default void abs() {
        
        System.out.println("hi");
    }
    default void abc() {
            
            System.out.println("hi");
        }
    static void aaa() {
        System.out.println("in aaa");
    }
    static void bbb() {
        System.out.println("in bbb");
    }
}


public class FunDemo {
    public static void main(String[] args) {
        Foo foo = ()->{
            System.out.println("aa");
            return 0;};
            foo.run(); //函数式接口调用
            foo.abs(); //默认的可以有多个
            Foo.aaa(); // 静态方法直接类应用,
    }
}
函数式接口 lamdba编程

Arraylist:https://www.cnblogs.com/msymm/p/9872818.html

3 ArrayList源码解析

总结
(01) ArrayList 实际上是通过一个数组去保存数据的。当我们构造ArrayList时;若使用默认构造函数,则ArrayList的默认容量大小是10
(02) 当ArrayList容量不足以容纳全部元素时,ArrayList会重新设置容量:新的容量=“(原始容量x3)/2 + 1”。:hashmap的初始值是16每次扩容是乘以2:hashset 容器的大小始终是2的幂,默认为16不在赘述
(03) ArrayList的克隆函数,即是将全部元素克隆到一个数组中。
(04) ArrayList实现java.io.Serializable的方式。当写入到输出流时,先写入“容量”,再依次写入“每一个元素”;当读出输入流时,先读取“容量”,再依次读取“每一个元素”。

Arraylist的是线程不安全会出现并发修改异常:(在大并发中还是使用vector或者CopyOnWriteArrayList:vector在操作的时候是会锁住整个list所以不太好,)

例如:

package work;



import java.util.ArrayList;
import java.util.List;



public class run_test {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        
        for (int i = 0; i < 3; i++) {
            new Thread(()->{
                list.add("a");
                System.out.println(list);}).start();
            
        }
        
    }
}
并发修改异常

结果:

有时候也会这样:正确的是这样

解决办法: 1. new vector

      2. collections.synchornizedlist(new ArrayList<>())

       3. copyonwriteArraylist()  // 并发时推荐写时复制

       set时使用:copyonwriteArraySet()

        map时使用:concurrentHashMap

       

写时复制  copyonwrite 容器即是写时复制的容器,网一个容器添加元素的时候不直接网=往当前容器的object[ ] 添加,二十先将容器Object[ ]进行copy。复制出一个新的容器Object [ ] newElements, 然后往新的Object [ ] newElements里面添加元素,添加完元素之后,在将原容器的应用指向新的容器SetArray(newElements)。这样做的好处是可以copyonwrite容器进行并发的读,而不需要加锁,羊为当前容器不会添加任何元素。所以copyonwrite容器也是一种读写分离的思想,读和写不同的容器。

1. 接口不可以实例化,为什么我们写的接口可以new呢?是因为我们的编译器在编译的时候自动生成了一个program的类(这就是为什么list接口不可以new但是我们自己写的接口却可以new)

HashSet的底层是Hashmap  为什么hashmap可以变成hashset呢,是因为hashmao的k就是我们在set中输入的值,而value则是一个Object类型的 persent的常量(首先数组存储区间是连续的,占用内存严重,故空间复杂度很大,而且插入删除困难,但是hashmap底层运用到了哈希表,它综合了数组和链表的优点,查询、插入删除都相对简单,占用空间也小,所以底层运用hashmap。空对象就是为了凑HashMap的value值的,是一个虚拟值没什么用。)

多线程的编程模板套路:

  1.高内聚低耦合前提下,线程操作资源类

  2.判断/干活/通知

  3. 防止虚假唤醒   //在多个线程并行中判断为了防止错误判断最好用while循环而不是if

package day_one;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.TimeUnit;

public class Runner {
    private int num=0;
    public synchronized void incry() throws Exception {
        while (num!=0) {
            this.wait();
        }
        Thread.sleep(400);
        num++;
        System.out.println(Thread.currentThread().getName()+"	"+"num is:"+num);
        this.notifyAll();
    }
    
    public synchronized void decry() throws Exception {
        while (num==0) {
            this.wait();
        }
        Thread.sleep(300);
        num--;
        System.out.println(Thread.currentThread().getName()+"	"+"num is:"+num);
        this.notify();
    }
    
    public static void main(String[] args) {

        Runner runner = new Runner();
        
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    runner.incry();
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();}}}, "a").start();
        
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    runner.decry();
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();}}}, "a").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    runner.incry();
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();}}}, "c").start();
        
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    runner.decry();
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();}}}, "d").start();
        

    }
}
多线程的虚假唤醒:多线程的交互判断不许用if这里用while,注意这里是synchronized锁和wait和notiyf产生的效果
a    num is:1
d    num is:0
c    num is:1
a    num is:0
c    num is:1
a    num is:0
c    num is:1
a    num is:0
c    num is:1
a    num is:0
c    num is:1
a    num is:0
c    num is:1
a    num is:0
c    num is:1
a    num is:0
c    num is:1
a    num is:0
c    num is:1
a    num is:0
c    num is:1
a    num is:0
a    num is:1
d    num is:0
a    num is:1
d    num is:0
a    num is:1
d    num is:0
a    num is:1
d    num is:0
a    num is:1
d    num is:0
代码结果
原文地址:https://www.cnblogs.com/BookMiki/p/14092903.html