• java并发编程看这一篇就够了


    知识储备

    同步和异步

    同步:A去公司前台找B,B不在,A一直等B。
    异步:A去公司前台找B,B不在,A回去了,B什么时候在了通知A。

    并发和并行

    并发:一个饮水机,大家交替接水喝。
    并行:两个饮水机,两个人同时接水喝。

    共享资源

    A和B同时进一个厕所,只有一个人可以进厕所。

    为什么要使用并发

    提高系统性能

    JMM

    java memory model 翻译为 java 内存模型

    可见性

    线程一修改共享变量是否对线程二可见。

    原子性

    一系列操作是否是一个不可分割的,也就是常说的同时成功或同时失败。

    有序性

    指令重排序,不是按照写代码的顺序进行执行。

    线程的状态

        public enum State {       
            NEW,
            RUNNABLE,
            BLOCKED,
            WAITING,
            TIMED_WAITING,
            TERMINATED;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    下面我们用一个实例来看看线程的所有状态

    public class UseThread {
    
        static UseThread obj = new UseThread();
    
        public static void main(String[] args) throws Exception {
            Thread t1 = new Thread(() -> {
                UseThread.testBlock();
            }, "thread-01");
    
            Thread t2 = new Thread(() -> {
                UseThread.testBlock();
            }, "thread-02");
            //线程t2创建 new
            System.out.println(System.currentTimeMillis() + " " + t2.getName() + ":" + t2.getState());
            t1.start();
            t2.start();
            //线程二启动 RUNNABLE
            System.out.println(System.currentTimeMillis() + " " + t2.getName() + ":" + t2.getState());
            while (true) {
                Thread.sleep(100);
                System.out.println(System.currentTimeMillis() + " " + t2.getName() + ":" + t2.getState());
                if ("TERMINATED".equals(t2.getState().toString())) {
                    break;
                }
            }
    
            System.out.println("------");
    
            Thread t3 = new Thread(() -> {
                UseThread.testWait();
            }, "thread-03");
    
            Thread t4 = new Thread(() -> {
                UseThread.testNotify();
            }, "thread-04");
            t3.start();
            Thread.sleep(50);
            System.out.println(System.currentTimeMillis() + " " + t3.getName() + ":" + t3.getState());
            t4.start();
    
        }
    
    
        public static void testBlock() {
            synchronized (obj) {
                System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "抢到了锁");
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                }
                System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "释放锁");
            }
        }
    
    
        public static void testWait() {
            synchronized (obj) {
                System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "抢到了锁");
                try {
                    obj.wait();
                    System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "我被唤醒了");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "释放锁");
            }
        }
    
        public static void testNotify() {
            synchronized (obj) {
                System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "抢到了锁");
                obj.notify();
                System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "释放锁");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                }
            }
        }
    }
    --------
    1656144877610 thread-02:NEW
    1656144877610 thread-02:RUNNABLE
    1656144877611 thread-01抢到了锁
    1656144877712 thread-02:BLOCKED
    1656144877813 thread-01释放锁
    1656144877813 thread-02抢到了锁
    1656144877814 thread-02:TIMED_WAITING
    1656144877914 thread-02:TIMED_WAITING
    1656144878014 thread-02:TIMED_WAITING
    1656144878015 thread-02释放锁
    1656144878114 thread-02:TERMINATED
    ------
    1656144878114 thread-03抢到了锁
    1656144878165 thread-03:WAITING
    1656144878165 thread-04抢到了锁
    1656144878165 thread-04释放锁
    1656144879169 thread-03我被唤醒了
    1656144879169 thread-03释放锁
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99

    结果分析:

    线程二刚创建的状态为 NEW ,执行start方法后变为RUNNABLE,线程t1持有锁的200毫秒内,t2是BLOCKED状态。t2持有锁的过程中睡眠200毫秒是TIMED_WAITING状态。t2执行完后是TERMINATED状态。

    juc的结构

    聊到juc就不得不提一下 Doug Lea 并发包之父
    在这里插入图片描述

    CompletableFuture

    继承关系

    CompletableFuture

    runAsync

    接口直接返回success,两秒后异步线程完毕,执行方法a。

     @Override
        public String test() {
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                stringRedisTemplate.opsForValue().set("k1", "v1");
                log.info("{} sync k1 v1 ...", Thread.currentThread().getName());
            });
            future.whenComplete((r, e) -> {      
                a();
            });
            log.info("start return ...");
            return "succes";
        }
    
    
        public void a() {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("{} sync k2 v2 ...", Thread.currentThread().getName());
            stringRedisTemplate.opsForValue().set("k2", "v2");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    在这里插入图片描述

    supplyAsync

    有返回值,通过whenComplete方法的r和e来获取相应的执行结果和异常。

     @Override
        public String test() {
            CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                stringRedisTemplate.opsForValue().set("k1", "v1");
                log.info("{} sync k1 v1 ...", Thread.currentThread().getName());
                return "this is result ";
            });
            future.whenComplete((r, e) -> {
                log.info("result = {} error = {}", r, e.getMessage());
                a();
            });
            log.info("start return ...");
            return "succes";
        }
    
        public void a() {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("{} sync k2 v2 ...", Thread.currentThread().getName());
            stringRedisTemplate.opsForValue().set("k2", "v2");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    在这里插入图片描述
    我们将代码稍作改造,获取异常。
    在这里插入图片描述

    在这里插入图片描述

    whenComplete

    获取执行结果,默认为异步,由异步线程1执行任务a。

    在这里插入图片描述

    whenCompleteAsync

    由异步线程2执行任务a。
    在这里插入图片描述

    get

    在这里插入图片描述
    修改为get则会阻塞直到任务完成

    在这里插入图片描述
    可以看到接口返回的结果已经发生改变。
    在这里插入图片描述

  • 相关阅读:
    EasyExcel 模板导出excel、合并单元格及单元格样式设置。 Freemarker导出word 合并单元格
    TSP:常春藤算法IVY求解旅行商问题TSP(可以更改数据),MATLAB代码
    源码详解Spring请求处理过程
    Java Day2(Java基础语法)
    基于ASP.NET MVC + Bootstrap的仓库管理系统
    JavaScript 56 JavaScript 调试
    cxf反向根据.net wsdl内容生成服务器端代码
    数据结构与算法_二叉搜索树
    十大排序详解
    记一次 .NET 某打印服务 非托管内存泄漏分析
  • 原文地址:https://blog.csdn.net/qq_37151886/article/details/125452615