JUC 总结

JUC课堂笔记

COW 的思想:(不要害怕看源码,因为到了最底层都是你能够看懂的代码)

多看阿里巴巴开发手册!

1、所有的知识,你能吸收多少,更多取决于自己,自律性!

2、老师讲的所有的知识,就好比一座山,能搬走多少看自己的努力

3、下去要多巩固,多看,多问!

4、对自己的学习结果负责

1.什么是JUC

2.进程和线程

架构:高内聚,低耦合

多线程编程的pattern:

1 先有一个资源类

2 然后多线程操纵资源类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gHaANxwt-1583501035630)(C:\Users\quinc\AppData\Roaming\Typora\typora-user-images\image-20200301225414992.png)]

线程之间通信:判断、执行、通知

wait 和 sleep区别

(JUC版sleep: 用TimeUnit类,例如TimeUnit.SECONDS.sleep(2)):

wait sleep
调用者 Object对象 Thread类静态调用
释放锁 Y N
使用范围 与notify成组使用、用于线程通信 单独使用、哪里都可以用
异常捕获 可以不捕获 需捕获
  • synchronized 和 Lock 区别:

synchronized java.util.concurrent.locks.Lock
语法 关键字 接口
尝试获取锁 N、若A获得则B一直等待 Y、可尝试获取若失败则放弃
自动释放锁 Y N
公平锁 N 默认非公平、可设置
精准控制 N、适合代码量小的同步 Y

3.Lock锁

独占锁(写锁):一次只能被一个线程占有
共享锁(读锁):该锁可以被多个线程占有

集合/队列

不安全集合类 安全集合类
ArrayList CopyOnWriteArrayList
HashSet CopyOnWriteArraySet
HashMap ConcurrentHashMap
  • 4组API:队列一般可以检测第一个元素是谁!
方法 第一组会抛出异常 返回一个布尔值,不会抛出异常 延时等待 一直等待(阻塞)
插入 add() offer(e) offer(e,time) put()
取出 remove() poll() poll(time) take()
检查 element() peek() - -

4、生产者消费者问题notify and wait

虚假唤醒->用while代替if

https://www.cnblogs.com/set-cookie/p/8728907.html

线程之间的通信design pattern: 判断 执行 通知

  • ConditionCondition
  • [CountDownLatch] (https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html)
  • Semaphore

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6NZhbOhz-1583501035632)(C:\Users\quinc\AppData\Roaming\Typora\typora-user-images\image-20200306214259538.png)]

copyonwriteLIST

CopyonWriteSet

concurrentHashmap

ReentrantReadWriteLock

5 8锁问题

牢记基本原理:被 synchronized 修饰的方式,锁的对象是方法的调用者。如果是放在函数级别的syncronized修饰符,那么是class级别的。

小结

1、new this 调用的这个对象,是一个具体的对象!

2、static class 唯一的一个模板!

synchronized JUC版
判断条件 Object Condition
等待方法 wait await
通知方法 notify/notifyAll signal/signalAll

6 不安全得集合类

不安全集合类 安全集合类
ArrayList CopyOnWriteArrayList
HashSet CopyOnWriteArraySet
HashMap ConcurrentHashMap
  • 4组API:队列一般可以检测第一个元素是谁!
方法 第一组会抛出异常 返回一个布尔值,不会抛出异常 延时等待 一直等待(阻塞)
插入 add() offer(e) offer(e,time) put()
取出 remove() poll() poll(time) take()
检查 element() peek() - -

7 读写锁

ReentrantReadWriteLock https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html

8 阻塞队列

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-apExY4pM-1583501035633)(C:\Users\quinc\AppData\Roaming\Typora\typora-user-images\image-20200306220529969.png)]

插入 add() offer(e) offer(e,time) put()
取出 remove() poll() poll(time) take()
方法 第一组会抛出异常 返回一个布尔值,不会抛出异常 延时等待 一直等待
检查 element() peek() - -

彩蛋:同步队列

SynchronousQueue , 只有一个容量!

每一个put操作,就需要有一个 take操作!

9 线程池

为什么要用线程池?线程复用。(不用回答太多废话)

为什么阿里不允许使用executors 去创建线程池?

《阿里巴巴开发规范手册》提醒:这种创建线程池的方式忌用,因为 容易引起 OOM。源码中,Integer.MAX_VALUE 最大达到 21亿4千7百万,一般电脑是不可能做到,危害性不言而喻。

  • 3大方法

    ExecutorService threadPool = Executors.newSingleThreadExecutor();
    固定的线程数
    ExecutorService threadPool = Executors.newFixedThreadPool(8);
    // 遇强则强!可伸缩!
    ExecutorService threadPool = Executors.newCachedThreadPool();

  • 7大参数

    public ThreadPoolExecutor(int corePoolSize, // 核心池线程数大小 (常用)
    int maximumPoolSize, // 最大的线程数大小 (常用)
    long keepAliveTime, // 超时等待时间 (常用)
    TimeUnit unit, // 时间单位 (常用)
    BlockingQueue workQueue, // 阻塞队列(常用)
    ThreadFactory threadFactory, // 线程工厂
    RejectedExecutionHandler handler // 拒绝策略(常用)) {

  • 4种拒绝策略:

      * 1、ThreadPoolExecutor.AbortPolicy();  抛出异常,丢弃任务
         * 思路:看到效果一样的东西,可以研究研究!
         * 2、ThreadPoolExecutor.DiscardPolicy();不抛出异常,丢弃任务
         * 3、ThreadPoolExecutor.DiscardOldestPolicy(); 尝试获取任务,不一定执行!
         * 4、ThreadPoolExecutor.CallerRunsPolicy(); 哪来的去哪里找对应的线程执行!
    
public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue());
}
public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue()));
}
new ThreadPoolExecutor.DiscardPolicy());

线程数设定:

CPU密集型(计算密集型) 最大线程数=CPU核数=Runtime.getRuntime().availableProcessors(); 推荐使用Stream接口
IO密集型: 最大线程数=IO任务的倍数、不能低于IO任务的数量;使用CompletableFuture灵活性更好

总结一下:io操作多的的线程个数公式跟CPU密集型的不一样。最佳线程数目 = (线程等待时间与线程CPU时间之比 + 1)* CPU数目

10 4个函数式接口

所有的函数式接口,函数式接口是我们现在必须要掌握且精通的

Function 传入一个参数, 输出一个参数
cousumer(消费者) 传入一个参数 不输出参数
supplier(生产者) 没有输入参数 只有输出参数
predicate 传入一个参数 返回判断值(Boolean)

11 stream 流计算

大数据时代重点: 存储和计算

1.5 枚举,反射,注解,泛型

1.8 functional, stream,lamda,链式编程

Stream的原理:

上文中已经提到了在Java 8引入了自动并行化的概念。它能够让一部分Java代码自动地以并行的方式执行,也就是我们使用了ForkJoinPool的ParallelStream。

Java 8为ForkJoinPool添加了一个通用线程池,这个线程池用来处理那些没有被显式提交到任何线程池的任务。它是ForkJoinPool类型上的一个静态元素,它拥有的默认线程数量等于运行计算机上的处理器数量。当调用Arrays类上添加的新方法时,自动并行化就会发生。比如用来排序一个数组的并行快速排序,用来对一个数组中的元素进行并行遍历。自动并行化也被运用在Java 8新添加的Stream API中。

package com.coding.future;

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

public class CompletableFutureDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 没有返回值,好比多线程,功能更强大!
// CompletableFuture completableFuture = CompletableFuture.runAsync(() -> {
// try {
// TimeUnit.SECONDS.sleep(2);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// System.out.println(Thread.currentThread().getName() + “没有返回值!”);
// });
// System.out.println(“111111”);
// completableFuture.get();

    // 有返回值
    // 任务
    CompletableFuture uCompletableFuture = CompletableFuture.supplyAsync(() -> {
        System.out.println(Thread.currentThread().getName()+"=>supplyAsync!");
        int i = 10/0;
        return 1024;
    });

    System.out.println(uCompletableFuture.whenComplete((t, u) -> { // 成功
        System.out.println("t=>" + t); // 正确结果
        System.out.println("u=>" + u); // 错误信息
    }).exceptionally(e -> { // 失败,如果错误就返回错误的结果!
        System.out.println("e:" + e.getMessage());
        return 500;
    }).get());

}

}

12、分支合并

什么是 forkjoin

MapReduce:input->split->map->reduce->output

主要就是两步:

1、任务拆分

2、结果合并

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QGKSz1wB-1583501035634)(E:/WorkingDocument/2020艾编程相关/3.4号 JUC(中)/Juc并发编程课堂笔记.assets/image-20200304223011997.png)]

前提:forkjoin 一定是用在大数据量的情况下

工作原理:工作窃取 底层维护的是一个双端队列;

好处:效率高

坏处:产生资源争夺

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DV5S1BpT-1583501035634)(E:/WorkingDocument/2020艾编程相关/3.4号 JUC(中)/Juc并发编程课堂笔记.assets/image-20200304223252511.png)]

测试一下Forkjoin

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hoERi3ZI-1583501035635)(E:/WorkingDocument/2020艾编程相关/3.4号 JUC(中)/Juc并发编程课堂笔记.assets/image-20200304223538382.png)]

13、异步回调

Future

CompletableFuture

代码测试

package com.coding.future;

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

public class CompletableFutureDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 没有返回值,好比多线程,功能更强大!
//        CompletableFuture completableFuture = CompletableFuture.runAsync(() -> {
//            try {
//                TimeUnit.SECONDS.sleep(2);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            System.out.println(Thread.currentThread().getName() + "没有返回值!");
//        });
//        System.out.println("111111");
//        completableFuture.get();

        // 有返回值
        // 任务
        CompletableFuture<Integer> uCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName()+"=>supplyAsync!");
            int i = 10/0;
            return 1024;
        });

        System.out.println(uCompletableFuture.whenComplete((t, u) -> { // 成功
            System.out.println("t=>" + t); // 正确结果
            System.out.println("u=>" + u); // 错误信息
        }).exceptionally(e -> { // 失败,如果错误就返回错误的结果!
            System.out.println("e:" + e.getMessage());
            return 500;
        }).get());

    }
}

补充知识常见面试问题:

能用lamda表达式得地方就用lamda表达式,取代匿名类!

volatile与threadlocal

Volatile 保证原子操作(包括long&double,还有基本类型)跟禁止指令重排。ThreadLocal模板类是某一个线程里面保存一个副本,但是值的有效性是要程序自己更新的.

主存会自动修改线程的副本 支持类型
Volatile Y 基本类型,引用类型只能保证引用的更新。
ThreadLocal N 模板类,支持存储各种class

https://www.zhihu.com/question/31990408

https://blog.csdn.net/qq_31489805/article/details/78456048

https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html

https://www.ibm.com/developerworks/java/library/j-jtp06197/

volatile" serves multiple purposes:

· guarantees atomic writes to double/long

· guarantees that when a thread A sees change in volatile variable made by thread B, thread A can also see all other changes made by thread B before the change to volatile variable (think setting the number of used cells in array after setting the cells themselves).

· prevents compiler optimization based on assumption that only one thread can change the variable (think tight loop while (l != 0) {}.

ThreadLocal

instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ThreadLocal.html

Class ThreadLocal

Example:

public class ThreadLocalExample {
 
    public static void main(String[] args) {
        MyRunnable sharedRunnableInstance = new MyRunnable();
 
        Thread thread1 = new Thread(sharedRunnableInstance);
        Thread thread2 = new Thread(sharedRunnableInstance);
 
        thread1.start();
        thread2.start();
 
        thread1.join(); //wait for thread 1 to terminate
        thread2.join(); //wait for thread 2 to terminate
    }
 
}
public class MyRunnable implements Runnable {
 
    private ThreadLocal threadLocal = new ThreadLocal();
 
    @Override
    public void run() {
        threadLocal.set( (int) (Math.random() * 100D) );
 
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
        }
 
        System.out.println(threadLocal.get());
    }
}

java能够创建线程吗? 不能!

原因是因为?

面试手写题:单例模式、排序算法、死锁、生产者消费者

你可能感兴趣的:(听课记录)