精华内容
下载资源
问答
  • 模块化比特币全节点微服务API服务器体系结构和实用程序工具包,可构建可扩展,安全且功能强大的应用程序和服务,而无需可信任的第方。 什么是cyphernode? Cyphernode托管服务和商业比特币API(例如Blockchain....
  • 在这近个月的学习中,对自身成长较;也了解了关于区块链的一些浅薄的知识,并且涉足web安全领域,总体来说这个月还是比较充实和快乐的;区块链(Blackchain)技术的生产发展离不开比特币,首先因为随着比特...

    本人于三月底有幸入职区块链公司;在这近三个月的学习中,对自身成长较大;也了解了关于区块链的一些浅薄的知识,并且涉足web安全领域,总体来说这三个月还是比较充实和快乐的;
    区块链(Blackchain)技术的生产发展离不开比特币,首先是因为随着比特币的诞生, 作为比特比底层技术的区块链技术才得以公之于众;其次,因为比特币是截至目前区块链技术中最为人知的应用案例。比特的概念出自中本聪;在2008年发表的论文,Bitcoin:A peer-to-peer Electroinic Cash System中首次提出,在论文中,中本聪将区块链技术作为构建比特币数据结构及交易体系的基础技术,将比特币打造为一种数字货币和在线支付系统,利用加密技术实现资金转移,而不再依赖于中央银行。身份信息的匿名(区块链最近几年大火并不是偶然,因为人们越来越重视自己的隐私信息;而区块链正是承载这种体系,例如:Telegram的崛起,并不是偶然。)交易确认的过程则需要用户贡献算力,共同对交易进行共识确认,从而将交易记录到全网的公开账本中;现在已经有过万钟加密数字货币;但比特币约占所有加密货币市值的90%;
    区块链的特点;
    区块链具有去中心化、时序数据、集体维护、可编程、安全可信和匿名性等特点;
    1、去中心化
    区块链数据的验证、记账、存储、维护和传输等过程均基于分布式系统架构、采用纯数学方法而不是中心机构来建立分布式节点间的信任体系,从而形成去中心化的可信任的分布式系统;
    2、时序数据
    区块链采用带有时间戳的链式区块结构存储数据,从而为数据增加了时间维度,具有极强的可验证性和可追溯性;
    3、集体维护
    区块链系统采用特定的经济激励机制来保证分布式系统中所有节点均可参与数据区块的验证过程(比如加密货比的挖矿过程),并且通过共识算法来选择特定的节点将新区块添加到区块链;
    4、可编程
    区块链技术可提供灵活的脚本代码系统,支持用户床架够啊记得智能合约、货币或其他去中心化应用,例如:以太坊(Ethereum)平台即提供了图灵完备的脚本语言以供用户来构建任何可以精确定义的智能合约或交易类型;
    5、安全可信
    区块链技术采用非对称密码学原理对数据进行加密,同时借助分布式系统节点的工作量证明等共识算法形成的强大算力来抵御外部×××,保证区块链数据不可篡改和不可伪造,因为具有较高的安全性;
    6、匿名性
    由于节点之间的交换遵循固定的算法,其数据交互是无需信任的(区块链中的数据规则会自行判断活动是否有效),因此交易对手无需通过公开身份的方式让对方对自己产生信任,对信用的累计非常有帮助;
    以上知识均是来自一本名为《区块链技术原理及底层架构》的书籍,本人只是将学到的知识作为分享到线上,让更多人明白其实区块链并不是一种传销机制,它是一种新兴的网络传输体系,去中心化思想、匿名性足以让其在网络发展中立下不可磨灭的一笔;

    以梦为马,不负韶华。我们,只关注技术;

    转载于:https://blog.51cto.com/msylinux/2130348

    展开全文
  • 中国石油大学《安全管理学》2

    千次阅读 2020-10-15 09:59:16
    2.什么是安全生产责任制。 答:安全生产责任制企业的基本制度,根据“管生产必须管安全”的原则,对企业各级领导和各类人员明确规定在安全生产中应负的责任,企业中最基本的一项安全制度,安全管理制度的...

    2.什么是安全生产责任制。

    答:安全生产责任制是企业的基本制度,是根据“管生产必须管安全”的原则,对企业各级领导和各类人员明确规定在安全生产中应负的责任,是企业中最基本的一项安全制度,是安全管理制度的核心。

    3、根据《有毒作业分级》标准,简述有毒作业分级依据的三项指标内容。

    4、简述建立职业安全健康管理体系的基本步骤

    答:建立职业安全健康管理体系一般要经过下列四个基本步骤:
    (1)职业安全健康管理体系的策划与准备;
    (2)职业安全健康管理体系文件的编制;
    (3)职业安全健康管理体系试运行;
    (4)职业安全健康管理体系的内部审核与管理评审。

    5、简述应急预案编制的基本步骤。

    1. 简述事故应急演练基本过程由哪几个阶段组成,以及每个阶段的主要任务。

    答: 

    1、确定演练目2113明确举办应急5261演原因、演练要的问题和期4102望达到的效果等1653。
    2、分练需求,在对事先设定事件的风险及应急预案进行认真分析的基础上,确定需调整的演练人员、需锻炼的技能、需检验的设备、需完善的应急处置流程和需进一步明确的职责等。

    3、确定演练范围,根据演练需求、经费、资源和时间等条件的限制,确定演练事件类型、等级、地城、参演机构及人数、演练方式等。演练需求和演练范围往往互力影响。

    更多内容请加VX:chenjing-1125

    展开全文
  • 基于自身改善的渴望、市场的形势、客户的要求,近十年来,我国各类企业正在实施ISO9001质量、ISO14001环境、ISO45001职业健康与安全、精益生产、6SIGMA等诸多管理体系,少则两个管理体系,多则八九个。 随着国内外...

    如何将三体系进行整合,是一个较为系统且复杂的问题。加之最近几年,从ISO9001到ISO14001,再到ISO45001,标准一直在换版,新标准都有了新的变化和要求。因此,今天这篇文章将从整合的思路、步骤等内容进行思考,仅供参考。
    在这里插入图片描述
    一、为什么要整合?
    基于自身改善的渴望、市场的形势、客户的要求,近十年来,我国各类企业正在实施ISO9001质量、ISO14001环境、ISO45001职业健康与安全、精益生产、6SIGMA等诸多管理体系,少则两三个管理体系,多则八九个。
    随着国内外形势的需要,越来越多已经建立和实施质量管理体系的企业开始引入其他管理体系,如环境管理体系、职业健康安全管理体系等,并申请第三方认证。
    企业要建立和保持两三个或N个管理体系的运行和认证证书资格,每年不得不投入相当大的人力、财力和时间资源。
    由于三个独立的管理体系运作不利于企业的经营发展,整合管理与认证成为必然。再加上其他管理体系在标准的思想、标准要素等内容上有很强的关联性,都是建立在质量管理体系的框架之上,都贯穿了八项基本管理原则,体系的运行模式、文件的架构基本相同,这样就为整合管理体系提供了技术可能。
    整合管理体系的现实意义在于以下方面:
    1、用一套体系文件进行统一控制,有利于简化企业内部管理,降低企业管理成本,实现企业绩效增值。
    2、企业的管理功能和效率发挥的好坏靠的是管理体系的整体有效性的发挥。一体化管理体系有利于提高企业管理水平,提高企业管理效率,提高执行力。
    3、涵盖多种认证的一体化管理体系有利于增强企业自我发展和自我完善,提升市场竞争力。
    二、独立运行存在的问题?
    三体系的建立,有效促进了质量、环境、职业健康安全工作。在运行管理中,我们按照体系标准、体系要素和法律法规的要求,针对生产工艺流程中可能发生的质量、环境、安全等问题,实施全员、全方位、全过程的运行控制,运用PDCA运行模式的手段和方法,强化管理,持续改进,使企业管理不断上水平。同时,在运行中我们也发现以下问题:
    1、同一部门在工作中执行三套体系,造成职责不一致、行动不统一。
    2、在同一生产工艺流程、统一工作程序上三套体系文件中均有要求时,造成重复性开展、重复记录。
    3、内部审核时,三套体系单独进行,形成同一记录、同一工作重复审核。
    4、管理评审时,三套体系单独进行,增加评审次数和会议次数,评审的质量和效果不太理想。
    5、三个体系在贯标认证初始编制的体系文件,在某些方面与生产经营实际不符,造成“两张皮”现象。
    6、对三个体系知识培训的力度不够,领导作用、全员参与的重视程度上还存有差距。
    7、传统管理的决策、方法上的习惯性,时有与三套体系的相关要求不一致现象,部分管理者和员工不能正确认识和使用三套体系这个工具,运用到生产经营的全过程即质量、环境、职业健康安全的各个方面中去。
    企业如何建立一个既有效同时满足三个标准的要求,又减少工作数量和运行层次,将质量管理体系、环境管理体系、职业安全健康管理体系整合成一个综合的管理体系呢?

    展开全文
  • 一、微分销是什么? 无论是线下还是线上,获客和流量都是高转化的前提。因此,为了解决这个问题,我们推出了扁平式发展分销商,让更多的卖家成为卖家,幅度降低销售成本。 微分销系统,让所有参与分享和推广的人...
  • 二十种设计模式【PDF版】

    热门讨论 2011-05-30 14:13:49
    如果你还不了解设计模式是什么的话? 那就先看设计模式引言 ! 学习 GoF 设计模式的重要性 建筑和软件中模式之异同 A. 创建模式 设计模式之 Singleton(单态/单件) 阎宏博士讲解:单例(Singleton)模式 保证...
  • 大学文献检索资料 DOC

    2009-11-28 10:35:24
    IPC以等级形式,将技术内容按部、类、小类、主组、分组逐级分类,组成一个完整的分类体系。 IPC共分为八大部,类号由A—H八个大写字母表示。 A部:人类生活需要 B部:作业;运输 C部:化学;冶金 D部:纺织...
  • 线程和进程与锁线程有几个状态wait和sleep区别lock锁(重点)lock锁与synchronized锁区别什么是锁 如何判断锁生产者与消费者问题JUC版本生产者消费者关系**8锁概念**静态方法 锁得概念集合类不安全...

    JUC 并发编程

    学习方法,学习新知识 要结合以前得旧知识 再结合实战 组成新知识 体系知识

    1.什么是juc

    源码+官方文档 学习方法

    在这里插入图片描述

    java.util 工具类、包、分类

    thread 普通线程代码

    runnable 效率低 callable效率高 有返回值

    2.线程和进程与锁

    进程:一个程序,qq.exe music.exe 程序集合;

    一个进程往往包含多个线程,至少包含一个!

    java默认有几个线程?2个 main GC

    线程:开了一个进程typora 比如我在写入 (自动保存)其实就是一个个线程在处理;

    java能开启线程嘛

    答:不可以得 因为java是一个虚拟机程序 不能去操作硬件 实际了 start方法调用本地native方法调用c++来开启线程

       private native void start0();
    

    并发、并行

    并发(多线程操作一个资源)

    • 单核cpu操作多个线程 其实是虚拟得 天下武功,唯快不破 其实就是快速交替

    并行(多个人以前行走)

    • cpu多核操作多个线程 线程池
    //查看cpu核数  
    public class Thread01 {
        public static void main(String[] args) {
            System.out.println(Runtime.getRuntime().availableProcessors());
        }
    

    并发编程核心:充分利用cpu资源

    所有公司都很看重

    企业-挣钱-提高效率-裁员 =一个厉害得人>=三个废物

    线程有几个状态

     public enum State {
          //新生
            NEW,
          //运行
            RUNNABLE,
          //阻塞
            BLOCKED,
          //等待 死死得等
            WAITING,
          //超时等待 一定时间
            TIMED_WAITING,
         //终止
            TERMINATED;
        }
    
    

    wait和sleep区别

    1.来自不同的类

    wait->object

    sleep->thread

    2.关于锁的释放

    wait会释放锁 等待 会主动释放

    sleep不会释放锁 抱着锁睡

    3.使用的范围不同

    wait 只能在同步代码块使用 配置notify 使用

    sleep 可以在任何地方使用 企业用法 timeunit

    TimeUnit.DAYS.sleep(1);
    

    4.是否需要捕获异常

    sleep 需要捕获异常

    wait 不需要捕获异常

    lock锁(重点)

    传统 synchronized 隐似同步锁
    
     Lock l = ...; l.lock(); try { // access the resource protected by this lock } finally { l.unlock(); } 
    

    在这里插入图片描述

    在这里插入图片描述

    公平锁:十分公平 先来后到 如果3s 3h 3h先到就要一直等待 才能执行3s的

    非公平锁:十分不公平,可以插队 (默认)

    LOCK锁代码

    package com.hy.lock;
    
    
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    /**
     * 买票案例
     * 企业级开发 降低耦合性 单一资源类
     * 多线程操作同一资源类
     */
    public class SaleTicketDemo02 {
        public static void main(String[] args) {
            Ticket ticket = new Ticket();
            new Thread(() -> { for (int i = 0; i < 60; i++) ticket.sale(); }, "A").start();
            new Thread(() -> { for (int i = 0; i < 60; i++) ticket.sale(); }, "B").start();
            new Thread(() -> { for (int i = 0; i < 60; i++) ticket.sale(); }, "C").start();
    
        }
    }
    class Ticket {
        /**
         * oop 写法
         * 属性
         * 方法
         */
        private int number = 50;  //总票数
        Lock lock=new ReentrantLock();
    
        public void sale() {
            lock.lock();  //加锁
            try {
                //业务代码
                if (number > 0) {
                    System.out.println(Thread.currentThread().getName() + "卖到啦第" + (number--) + "张票"+"剩余"+number+"票");
                }
            }catch (Exception e){
              e.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
    }
    
    

    lock锁与synchronized锁区别

    1. synchronized 内置的java关键字,lock是一个java类
    2. synchronized 无法判断获取锁的状态,lock可判断是否获取锁
    3. synchronized 会自动释放锁 lock必须手动释放 如果不释放就 deadlock
    4. synchronized 线程1(获取锁,阻塞)、线程2(等待 一直等);lock锁就不一定一直等待
    5. synchronized 可重入锁,不可以中断,非公平;lock 可重入锁,可以判断锁,非公平(可以设置)自由
    6. synchronized 适合锁少量代码同步问题,lock适合锁大量代码

    什么是锁 如何判断锁是谁

    synchronized 同步 就是锁 如果加在方法上锁得就是 调用者 如果锁得是静态的 就是锁类模板

    lock 默认锁得就是对象

    生产者与消费者问题

    synchronized 版  生产者与消费者
    
    /**
     * 生产者消费者 通信 关系
     * 线程 A B 同时操作一个资源
     * A ++
     * B --
     */
    public class SynchronizedCommunication {
        public static void main(String[] args) {
            Data data=new Data();
            //线程代码
            new Thread(()-> {
                for (int i = 0; i < 10; i++) {
                    try {
                        data.incrment();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"A").start();
            new Thread(()-> {
                for (int i = 0; i < 10; i++) {
                    try {
                        data.decrment();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"B").start();
        }
    }
    
    /**
     * 资源类
     * 判断等待 业务 通知
     */
    class Data{
        private  int number=0;
    
        public synchronized  void incrment() throws InterruptedException {
            if (number!=0){
                System.out.println(Thread.currentThread().getName()+"线程=>"+number);
                //释放锁 等待
                this.wait();
            }
            number++;
            //通知
            this.notifyAll();
        }
        public synchronized  void decrment() throws InterruptedException {
            if (number==0){
                System.out.println(Thread.currentThread().getName()+"线程=>"+number);
                //释放锁 等待
                this.wait();
            }
            number--;
            //通知
            this.notifyAll();
        }
    
    

    如果有 A B C D四条现场这样写就有问题存在 虚假唤醒

    因为if 只判断一次 所以改用while 会解决该问题

    JUC版本生产者消费者关系

    在这里插入图片描述

    通过新版得lock锁 实现 可以控制顺序执行线程 消费者生产者完美执行标准

    /**
     * lock 可以解决排序 问题 可以准确通知 下一个谁来执行
     */
    public class Block2 {
        public static void main(String[] args) {
            Data3 data3 = new Data3();
            new Thread(()-> { {
    
                    try {
                        for (int i = 0; i < 10; i++) {
                            data3.A();
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                }
            }},"A").start();
            new Thread(()-> { {
    
                try {
                    for (int i = 0; i < 10; i++) {
                        data3.B();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }},"B").start();
            new Thread(()-> { {
    
                try {
                    for (int i = 0; i < 10; i++) {
                        data3.C();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }},"C").start();
            new Thread(()-> { {
    
                try {
                    for (int i = 0; i < 10; i++) {
                        data3.D();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }},"D").start();
        }
    }
    class Data3{
       private Lock lock=new ReentrantLock();
        Condition condition1 = lock.newCondition();
        Condition condition2 = lock.newCondition();
        Condition condition3 = lock.newCondition();
        Condition condition4 = lock.newCondition();
       private int number=1;  //等于一个flag 标志位
        public void A() throws InterruptedException {
            try {
                lock.lock();
                while (number!=1){
                    condition1.await();
                }
                number=2;  //标志位1
                System.out.println(Thread.currentThread().getName()+"AAAAAA");
                //通知1 执行
                condition2.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //解锁
                lock.unlock();
            }
    
        }
        public void B() throws InterruptedException {
            try {
                lock.lock();
                while (number!=2){
                    condition2.await();
                }
                number=3;  //标志位1
                System.out.println(Thread.currentThread().getName()+"BBBBBB");
                //通知1 执行
                condition3.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //解锁
                lock.unlock();
            }
    
        }
        public void C() throws InterruptedException {
            try {
                lock.lock();
                while (number!=3){
                    condition3.await();
                }
                number=4;  //标志位1
                System.out.println(Thread.currentThread().getName()+"CCCCCC");
                //通知1 执行
                condition4.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //解锁
                lock.unlock();
            }
    
        }
        public void D() throws InterruptedException {
            try {
                lock.lock();
                while (number!=4){
                    condition4.await();
                }
                number=1;  //标志位1
                System.out.println(Thread.currentThread().getName()+"DDDDDD");
                //通知1 执行
                condition1.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //解锁
                lock.unlock();
            }
    
        }
    

    8锁概念

    package com.hy.lock;
    
    import java.util.concurrent.TimeUnit;
    
    /**
     * 8 kind of lock concept
     锁作为 关键字在方法上 默认锁得是 this 
     如果作用在代码块 锁得就是对象
     */
    public class CPhone {
        public static void main(String[] args) {
            //这里锁得就是check 锁得方法调用者  所以那个先调用 就那个先加锁
            Check check =new Check();
            new Thread(() ->{
            try {
                check.send();
                TimeUnit.SECONDS.sleep(1);
            }catch (Exception e){
                e.printStackTrace();
            }
            },"A").start();
            new Thread(() ->{ check.hello();},"B").start();
    
        }
    }
    
    /**
     * 资源类  符合 oop思想
     */
    class Check{
        public synchronized void  send(){
    
            try {
                System.out.println("发短信");
                TimeUnit.SECONDS.sleep(4);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        public synchronized void  call(){
            System.out.println("打电话");
        }
        public synchronized void hello(){
            System.out.println("hello");
        }
    }
    //这里先执行得就会是 发短信
    
    /**
     * 模拟 锁得 调用 静态 和 非静态区别
     */
    //这个时候执行得 打电话 因为锁得默认是对象调用者
    public class CPhone {
        public static void main(String[] args) {
            //其实就是两把锁
            //phone 被阻塞 但是 对象phone1也是调用者 所以也可以执行 所以就会直接执行
            Phone phone=new Phone();
            Phone phone1=new Phone();
            new Thread(() ->{
                try {
                    phone.send();
                    TimeUnit.SECONDS.sleep(1);
                }catch (Exception e){
                    e.printStackTrace();
                }
            },"A").start();
            new Thread(() ->{
                phone1.call();
                {
    
                }
            },"B").start();
    
        }
    }
    class Phone{
        public synchronized void send(){
    
            try {
                TimeUnit.SECONDS.sleep(5);
                System.out.println("发短信");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        public synchronized void call(){
            System.out.println("打电话");
        }
    }
    

    静态方法 锁得概念

    静态方法 多个对象 这个时候锁 锁得是类模板 class文件 默认只有一个 所以 先调用得对象 就会得到模板锁 其余得就不能调用啦 所以这里就会依旧是 A先执行

    /**
     * 模拟 锁得 调用 静态 和 非静态区别
     * 默认锁得是类模板  所以A线程先去调用 虽然有两个对象 但是模板只有一个 所以A调用了 等于模板加锁 所以要等A
     * 执行完毕 才能执行B
     */
    public class DPhone {
        public static void main(String[] args) {
            CD cd=new CD();
            CD cd1=new CD();
            new Thread(() ->{
                try {
                    cd1.call();
                    TimeUnit.SECONDS.sleep(1);
                }catch (Exception e){
                    e.printStackTrace();
                }
            },"A").start();
            new Thread(() ->{
                cd.send();
                {
    
                }
            },"B").start();
    
        }
    }
    
    class CD{
        public static synchronized void call(){
    
            try {
                TimeUnit.SECONDS.sleep(5);
                System.out.println("打电话");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        public static synchronized void send(){
            System.out.println("发短信");
        }
    }
    

    静态锁锁得是CLASS 和普通锁锁得是this 不是一个锁

    import java.util.concurrent.TimeUnit;
    /**
     * 模拟 锁得 调用 静态 和 非静态区别
     * 一个锁的是模板 一个锁得是调用者 等于两把锁 所以下面b会执行
     */
    public class DPhone {
        public static void main(String[] args) {
            CD cd=new CD();
            CD cd1=new CD();
            new Thread(() ->{
                try {
                    cd1.call();
                    TimeUnit.SECONDS.sleep(1);
                }catch (Exception e){
                    e.printStackTrace();
                }
            },"A").start();
            new Thread(() ->{
                cd.send();
                {
    
                }
            },"B").start();
    
        }
    }
    
    class CD{
        public static synchronized void call(){
    
            try {
                TimeUnit.SECONDS.sleep(5);
                System.out.println("打电话");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        public  synchronized void send(){
            System.out.println("发短信");
        }
    }
    

    集合类不安全

    COPYONWRITEARRAYLIST(LIST不安全)

       public static void main(String[] args) {
            /**
             * 这种就是不安全 解决方案
             * 1.直接用线程安全得 Vector
             * 2.可以使用 集合帮助类 调用synchronizedList 进行集合加锁得方法解决
             */
           // List list=new ArrayList();
           //方法1 List list=new Vector();
           //方法2  List list= Collections.synchronizedList(new ArrayList<>());
            /**
             * 为什么要用CopyOnWriteArrayList  写入时复制
             * 避免 覆盖数据 在写入得时候 复制一个 写完后在插入
             * Vector 和 copyarraylist区别 
             * Vector一个是 synchronized 所以性能方面 没有copyarraylist好
             * copyarraylist 用的是lock锁 所以性能要好很多
             */
            List list=new CopyOnWriteArrayList();
            for (int i = 1; i < 10; i++) {
                new Thread(() ->{{
                    list.add(UUID.randomUUID().toString().substring(0,5));
                    System.out.println(list);
    
                }
                },String.valueOf(i)).start();
            }
        }
    

    SET不安全

    和LIST 同理

    public class SetCur {
        /**
         * 和 list 同理
         * 不过set 只有两个解决方案
         * 1 使用帮助类 加锁
         * 2 CopyOnWriteArraySet
         * @param args
         */
        public static void main(String[] args) {
           // Set set = new HashSet<>();‘
           // Set<String> set = Collections.synchronizedSet(new HashSet<String>()
            Set set = new CopyOnWriteArraySet();
    
            for (int i = 1; i < 50; i++) {
            new Thread(() -> {
                {
                    set.add(UUID.randomUUID().toString().substring(0, 10));
                    System.out.println(set);
                    }
                }, String.valueOf(i)).start();
    
            }
        }
    

    hashSet 底层是什么

     public HashSet() {
            map = new HashMap<>();  //底层就是hashmap
        }
    //利用l map得key 因为key是不可重复得
     public boolean add(E e) {  //添加方法  
            return map.put(e, PRESENT)==null;
        }
    

    Map(不安全)

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

    • 内存一致性效果:与其他并发集合一样,在将对象放入ConcurrentMap作为键或happen-before之前的线程中的操作,在另一个线程中从ConcurrentMap访问或删除该对象之后

    主要是保证了原子性

    public class MapCur {
        public static void main(String[] args) {
           // Map<String, Object> map =new HashMap<>();
            Map<String, Object> map =new ConcurrentHashMap<>();
            for (int i = 0; i <50 ; i++) {
                 new Thread(()->{
                     map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(1,5));
                     System.out.println(map);
                 },String.valueOf(i)).start();
            }
        }
    

    ConcurrentHashMap

    1. 将当前 Segment 中的 table 通过 key 的 hashcode 定位到 HashEntry。
    2. 遍历该 HashEntry,如果不为空则判断传入的 key 和当前遍历的 key 是否相等,相等则覆盖旧的 value。
    3. 不为空则需要新建一个 HashEntry 并加入到 Segment 中,同时会先判断是否需要扩容。
    4. 最后会解除在 1 中所获取当前 Segment 的锁。
    5. 根据 key 计算出 hashcode 。
    6. 判断是否需要进行初始化。
    7. f 即为当前 key 定位出的 Node,如果为空表示当前位置可以写入数据,利用 CAS 尝试写入,失败则自旋保证成功。
    8. 如果当前位置的 hashcode == MOVED == -1,则需要进行扩容。
    9. 如果都不满足,则利用 synchronized 锁写入数据。
    10. 如果数量大于 TREEIFY_THRESHOLD 则要转换为红黑树。

    ConcurrentHashMap put源码

    public V put(K key, V value) {
        Segment<K,V> s;
        if (value == null)
            throw new NullPointerException();
        int hash = hash(key);
        int j = (hash >>> segmentShift) & segmentMask;
        if ((s = (Segment<K,V>)UNSAFE.getObject          // nonvolatile; recheck
             (segments, (j << SSHIFT) + SBASE)) == null) //  in ensureSegment
            s = ensureSegment(j);
        return s.put(key, hash, value, false);
    }
    

    ConcurrentHashMap get源码

    public V get(Object key) {
        Segment<K,V> s; // manually integrate access methods to reduce overhead
        HashEntry<K,V>[] tab;
        int h = hash(key);
        long u = (((h >>> segmentShift) & segmentMask) << SSHIFT) + SBASE;
        if ((s = (Segment<K,V>)UNSAFE.getObjectVolatile(segments, u)) != null &&
            (tab = s.table) != null) {
            for (HashEntry<K,V> e = (HashEntry<K,V>) UNSAFE.getObjectVolatile
                     (tab, ((long)(((tab.length - 1) & h)) << TSHIFT) + TBASE);
                 e != null; e = e.next) {
                K k;
                if ((k = e.key) == key || (e.hash == h && key.equals(k)))
                    return e.value;
            }
        }
        return null;
    }
    

    ConcurrentHashMap 1.8以后锁得是node 锁的粒度更低

    因为1.8后 改用数组 链表 达到阈值后使用红黑树 放弃了分段锁而是用了Node锁,减低锁的粒度,提高性能,并使用CAS操作来确保Node的一些操作的原子性,取代了锁。

    JDK1.7中,ConcurrentHashMap从过二次hash的方式(Segment -> HashEntry)能够快速的找到查找的元素。在1.8中通过链表加红黑树的形式弥补了put、get时的性能差距。

    hashtable 与 ConcurrentHashMap区别

    • 底层 数组和链表 1.8 到达最大阈值 可以设置位红黑树

    • hashtable put get每次都会进行同步锁

    • ConcurrentHashMap 里面是用的lock锁 所以比较高效 get乐观锁

    • ConcurrentHashMap get 只需要将 Key 通过 Hash 之后定位到具体的 Segment ,再通过一次 Hash 定位到具体的元素上。

      由于 HashEntry 中的 value 属性是用 volatile 关键词修饰的,保证了内存可见性,所以每次获取时都是最新值。

      ConcurrentHashMap 的 get 方法是非常高效的,因为整个过程都不需要加锁

    ConcurrentHashMap 采用了分段锁技术,其中 Segment 继承于 ReentrantLock。不会像 HashTable 那样不管是 put 还是 get 操作都需要做同步处理,理论上 ConcurrentHashMap 支持 CurrencyLevel (Segment 数组数量)的线程并发。每当一个线程占用锁访问一个 Segment 时,不会影响到其他的 Segment。

    Callable(easy)

    callable 怎么启动 原理探究

    runnable 的实现类 futuretask

    在这里插入图片描述

    futuretask 里面可以方callable 所以就实现啦 runnable和callable 连接 然后就可以间接使用 thread跑线程

    Constructor and Description
    FutureTask(Callable<V> callable)创建一个 FutureTask ,它将在运行时执行给定的 Callable
    FutureTask(Runnable runnable, V result)创建一个 FutureTask ,将在运行时执行给定的 Runnable ,并安排 get将在成功完成后返回给定的结果。

    最后就形成了完美解决方案 流程图

    在这里插入图片描述

    代码附上

    public class CallableTest {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
           // new Runnable()
    
         //new Thread().start();  //线程启动方式只有者一中
            /**
             * 用到 runnable线程实现类 FutureTask 间接和thread关联
             */
            MyThread myThread=new MyThread();
            FutureTask futureTask=new FutureTask<>(myThread);
            new Thread(futureTask).start();
            Integer o = (Integer) futureTask.get();
            System.out.println(o);
        }
    }
    class MyThread implements Callable<Integer>{
    
        @Override
        public Integer call() throws Exception {
            System.out.println("call()");
            return 1024;
        }
    }
    

    细节:有缓存 还会阻塞

    三大常用辅助类

    countDownLatch

    放代码。。。

    概念 类似于计数器 统计线程 线程跑完 关闭

    {
            //必须要执行任务的时候 在使用
            CountDownLatch countDownLatch=new CountDownLatch(6); //初始化 6个
            for (int i = 1; i <=6 ; i++) {
                new Thread(() -> {
                    System.out.println(Thread.currentThread().getName() + "god dd");
                    countDownLatch.countDown(); //每次-1
    
                }, String.valueOf(i)).start();
            }
            countDownLatch.await();  //线程等待结束 往下执行 结束
            System.out.println("god bye");
    
        }
     countDownLatch.countDown()  //每次执行减一
    
    countDownLatch.await();  //相当于计数器 当对于0 就唤醒向下执行结束
    

    cyclicBarrier

    概念 ++计数器 每次+1 直到得到设置结果 执行完毕

    /**
     * ++计数器
     * 加到一定量 就开启新的线程 执行结束
     */
    public class Cyclicbarrier {
        public static void main(String[] args) throws BrokenBarrierException, InterruptedException {
            CyclicBarrier cyclicBarrier=new CyclicBarrier(7,()-> {
                System.out.println(Thread.currentThread().getName() + "集齐龙珠召唤神龙");
            });
    
                for (int i = 1; i <=7; i++) {
    
                final int temp = i;
                new Thread(() -> {
                    System.out.println(Thread.currentThread().getName()+temp+"多少颗龙珠");
                    try {
                        cyclicBarrier.await(); //集齐了 然后通知线程执行
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }).start();
            }
    
            };
    

    semaphore

    程序计数器 使用场景 共享互斥 限流

    **
     * 程序计数器  限流 、
     * 停车场案例
     */
    public class semaphoreTest {
        public static void main(String[] args) {
            Semaphore semaphore=new Semaphore(5);  //设置默认能进入的数量
            for (int i = 1; i <10 ; i++) {
                new Thread(() -> {
                    try {
                        semaphore.acquire(); //获取
                        System.out.println(Thread.currentThread().getName()+"抢到车位");
                        TimeUnit.SECONDS.sleep(2);
                        System.out.println(Thread.currentThread().getName()+"离开车位");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
                        semaphore.release();  //释放资源 或者通知
                    }
    
                },String.valueOf(i)).start();
            }
        }
    

    semaphore.acquire() 获取资源

    semaphore.release() 释放资源

    读写锁

    ReadWriteLock

    • ReadWriteLock维护一对关联的locks ,一个用于只读操作,一个用于写入。 read lock可以由多个阅读器线程同时进行,只要没有作者。 write lock是独家的。

    独占锁(就是写锁)

    共享锁(就是读锁)

    上代码。。

    /**
         * 读写锁 案例  比如缓存 读取 和 写入 写只能一个线程 而读可以多线程
         * 读 写 (不能共存)
         * 读 读 (可以共存)
         * 写 写 (不能共存)
         */
        public class ReadWriteLockTest {
            //创建线程
            public static void main(String[] args) {
                MyCache myCache=new MyCache();
    
                for (int i = 1; i <10 ; i++) {
                  final int temp = i;
                    new Thread(()->{
                    myCache.put(temp+"",temp+"");
                },String.valueOf(i)).start();
             }
                for (int i = 1; i <10 ; i++) {
                    final int temp = i;
                    new Thread(()->{
                        myCache.get(temp+"");
                    },String.valueOf(i)).start();
                }
            }
        }
    
    
        //缓存cache资源类
        class MyCache{
            private  volatile Map<String, Object> map =new HashMap<>();
            private ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
    
            public void put(String key,Object value){
                  reentrantReadWriteLock.writeLock().lock();
                try {
                    //写锁 降低粒度
                    System.out.println(Thread.currentThread().getName()+"写入"+key);
                    map.put(key,value);
                    System.out.println(Thread.currentThread().getName()+"写入结束");
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    reentrantReadWriteLock.writeLock().unlock();
                }
            }
            public void get(String key){
                   reentrantReadWriteLock.readLock().lock();
                try {
                    System.out.println(Thread.currentThread().getName()+"读取"+key);
                    map.get(key);
                    System.out.println(Thread.currentThread().getName()+"读取结束");
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    reentrantReadWriteLock.readLock().lock();
                }
            }
    

    阻塞队列BlockingQueue

    BlockingQueue 不是新东西
    在这里插入图片描述

    队列概念 父子级别

    在这里插入图片描述

    使用场景 多线程 线程池

    四组Api

    方式 抛出异常 不抛异常有返回值 阻塞等待 超时等待
    添加 add offer put offer
    移除 remove poll take poll
    判断队列首 element element
    public static void test1(){
        BlockingQueue<String> blockingQueue=new LinkedBlockingQueue<>(3);
        System.out.println(blockingQueue.add("a"));
        System.out.println(blockingQueue.add("b"));
        System.out.println(blockingQueue.add("c"));
        //System.out.println(blockingQueue.add("d"));
        System.out.println(blockingQueue.element());  //判断队列首
        System.out.println("-----------------------------------");
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
    
    }
    
    public static void test2(){
        BlockingQueue<String> blockingQueue=new LinkedBlockingQueue<>(3);
        //如果超出了 就会返回false 不会抛出异常
        System.out.println(blockingQueue.offer("a"));
        System.out.println(blockingQueue.offer("b"));
        System.out.println(blockingQueue.offer("c"));
        System.out.println(blockingQueue.offer("d"));
        //System.out.println(blockingQueue.element());
        System.out.println("-----------------------------------");
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
    
    }
    
    public static void test3() throws InterruptedException {
        BlockingQueue<String> blockingQueue=new LinkedBlockingQueue<>(3);
        //阻塞 死死得等 如果没有 就一直等待
        blockingQueue.put("a");
        blockingQueue.put("a");
        blockingQueue.put("a");
    
        System.out.println(blockingQueue);
    
        //System.out.println(blockingQueue.element());
        System.out.println("-----------------------------------");
        System.out.println(blockingQueue.take());
        System.out.println(blockingQueue.take());
        System.out.println(blockingQueue.take());
    
    }
    
    public static void test4() throws InterruptedException {
        BlockingQueue<String> blockingQueue=new LinkedBlockingQueue<>(3);
        //超时等待  等到指定时间才会结束
        System.out.println(blockingQueue.offer("b"));
        System.out.println(blockingQueue.offer("c"));
        System.out.println(blockingQueue.offer("d"));
        System.out.println(blockingQueue.offer("a",5, TimeUnit.SECONDS));
        //System.out.println(blockingQueue.element());
        System.out.println("-----------------------------------");
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
    
    }
    

    synchronizedquery同步队列

    模拟代码

    public static void main(String[] args) {
        BlockingQueue<String> blockingQueue=new SynchronousQueue<>();
        new Thread(()->{
            try {
                System.out.println(Thread.currentThread().getName()+"PUT1");
                blockingQueue.put("1");
                System.out.println(Thread.currentThread().getName()+"PUT2");
                blockingQueue.put("2");
                System.out.println(Thread.currentThread().getName()+"PUT3");
                blockingQueue.put("3");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"T1").start();
        new Thread(()->{
            try {
                TimeUnit.SECONDS.sleep(3);
                System.out.println(Thread.currentThread().getName()+blockingQueue.take());
                TimeUnit.SECONDS.sleep(3);
                System.out.println(Thread.currentThread().getName()+blockingQueue.take());
                TimeUnit.SECONDS.sleep(3);
                System.out.println(Thread.currentThread().getName()+blockingQueue.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"T2").start();
    }
    

    线程池

    池化技术=》 优化资源使用

    线程池 连接池 对象池 常量池 都是为了 解决创建 销毁资源浪费

    池化技术 事先准备好资源 有人要用就来那 用完还给我

    线程池好处

    1. 降低资源得消耗
    2. 提高响应得速度
    3. 方便管理

    线程复用 可以控制最大并发数 方便管理

    //不过推荐 还是用这个创建线程次池
    //这是Executors 的原生手段
    public ThreadPoolExecutor(int corePoolSize, //默认大小
                              int maximumPoolSize, //最大线程
                              long keepAliveTime,  //超时等待时间
                              TimeUnit unit,  //单位
                              BlockingQueue<Runnable> workQueue) {  //阻塞队列
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }
    
    /**
     * 线程池得 三大方法
     * Executors 工具类
     */
    public class ThreadPool {
        public static void main(String[] args) {
            //ExecutorService service = Executors.newSingleThreadExecutor();//单一线程
           // ExecutorService service = Executors.newFixedThreadPool(5); //参数线程 默认5 最大5
            ExecutorService service =  Executors.newCachedThreadPool();  //缓存线程 伸缩版 哈哈哈
                try {
                    for (int i = 0; i < 10; i++) {
                        service.execute(() -> {
                            System.out.println(Thread.currentThread().getName() + "A");
                        });
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    service.shutdown();
                }
            }
    

    7大参数

    在这里插入图片描述

    /**
     * AbortPolicy 拒绝策略 如果超出线程和队列数 抛出异常
     * CallerRunsPolicy 哪来的回哪去 如果超出了 就回到来的线程 执行
     * DiscardPolicy  不抛出异常 直接丢弃
     *DiscardOldestPolicy 尝试和第一条竞争 失败照样给我丢弃啦
     * 承载最大 线程数+队列数
     * @param args
     */
    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 5, 3,
                TimeUnit.SECONDS, new LinkedBlockingQueue<>(3),
                Executors.defaultThreadFactory(), new ThreadPoolExecutor.DiscardOldestPolicy());
        try {
            for (int i = 0; i < 9; i++) {
                executor.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + "ok");
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            executor.shutdown();
        }
    }
    
    corePoolSize #初始线程数
    maximumPoolSize #最大线程数
    keepAliveTime   #超时策略
    TimeUnit        #单位
    BlockingQueue<Runnable> #队列
    threadFactory #线程工厂 默认 用工具类调用
    RejectedExecutionHandler #拒绝策略
    

    最大线程数定义(调优)

    IO密集型

    比较耗费资源的线程 找到 然后给定线程数>比较耗费资源的线程 一般都是双倍

    cpu密集型

    如何让资源使用到机制 判断运行时 cpu数量 来设置线程max

     Runtime.getRuntime().availableProcessors() //设置线程最大
    

    四大函数式接口(新时代必会)

    lambda 表达式 函数型接口 链式编程 stream流计算
    函数式接口 简化 编程
    foreaeh (消费者函数接口	)
    

    1.函数式接口 function

    源码

    public interface Function<T, R> {  //传递一个 t 返回一个R
    
        /**
         * Applies this function to the given argument.
         *
         * @param t the function argument
         * @return the function result
         */
        R apply(T t);
    
    public class FunctionTest {
        public static void main(String[] args) {
            Function stringFunction = new Function<String, String>() {
                @Override
                public String apply(String S) {
                    return r;
                }
            };
           //lombra 表达式写法 Function stringFunction = (s)->{return s;};
            System.out.println(stringFunction.apply("adada"));
        }
    

    2.Predicate 判断是否为空

    public class praticateTest {
        public static void main(String[] args) {
            Predicate predicate=new Predicate<String>() {
                @Override
                public boolean test(String o) {
                    return o.isEmpty();
                }
            };
            System.out.println(predicate.test(""));
        }
    }
    

    3.consumer 消费者函数型接口

    只有输入 没有返回

      public static void main(String[] args) {
    //        Consumer consumer=new Consumer<String>() {
    //            @Override
    //            public void accept(String o) {
    //                System.out.println(o);
    //
    //            }
    //        };
            Consumer consumer= (s)->{System.out.println(s);};
            consumer.accept("aaaa");
        }
    

    4.supplier 供给型接口 只有返回值

    只有返回 没有输入

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

    stream流式计算

    什么是流式计算

    存储数据 集合 mysql

    计算 stream流

    /**
     * 一分钟完成 只能一行代码
     * 5个 用户
     * id 为偶数
     * 年龄 23
     * 用户名转大写
     * 倒叙
     * 只显示一个用户
     */
    public class Test {
        public static void main(String[] args) {
            User u1=new User(1,"a",21);
            User u2=new User(2,"b",22);
            User u3=new User(3,"c",23);
            User u4=new User(4,"d",24);
            User u5=new User(6,"e",25);
    
            List<User> list= Arrays.asList(u1,u2,u3,u4,u5); //数组转换为list对象
      //链式编程
            list.stream()
                    .filter((u)->{return u.getId()%2==0; })  //过滤
                    .filter(u->{return u.getAge()>23;})      //过滤
                    .map(u->{return u.getName().toUpperCase();})   //名称转大写
                    .sorted((uu1,uu2)->{ return uu2.compareTo(uu1);})  //排序
                    .limit(1)  //控制显示
                    .forEach(System.out::println);
        }
    

    ForkJoin

    分支合并

    ForkJoin 并行执行任务 提高效率 大数据量

    大数据:map reduce(任务拆分 大任务 拆分成一个个小任务)

    概念图

    在这里插入图片描述

    ForkJoin特点 工作窃取

    /**
     * forkJoin 拆分操作
     */
    public class FaskJoinTest extends RecursiveTask<Long> {
       private Long start ;
        private Long end ;
        Long temp = 10_0000_0000L;
    
        public FaskJoinTest(Long start, Long end) {
            this.start = start;
            this.end = end;
        }
    
    
        @Override
        protected  Long compute() {
            if ((end - start) < temp) {
                Long sum = 0L;
                for (int i = 0; i < 1000000000; i++) {
                    sum += i;
                }
                return sum;
            } else {
                long limit = (end - start) / 2;
                FaskJoinTest faskJoinTest = new FaskJoinTest(start, limit);
                faskJoinTest.fork(); //拆分任务压缩到线程队列
                FaskJoinTest faskJoinTest1 = new FaskJoinTest(limit + 1, end);
                faskJoinTest1.fork();
    
    
                return faskJoinTest1.join() + faskJoinTest.join();
            }
    
        }
    }
    
     public static void main(String[] args) throws ExecutionException, InterruptedException {
          tset1();  //传统傻瓜式做法 时间 4174
           // test2();  //升级版 forkjoin程序员 时间:7556
           // test3();    //1999999999000000000  时间:384  流式速度最快
         privte volate Long SUM=2_0000_0000;
    
        }
        //方式1
        public static void tset1(){
            Long start=System.currentTimeMillis();
            Long sum=0L;
            for (int i = 0; i <20_0000_0000; i++) {
                sum+=i;
            }
            Long end= System.currentTimeMillis();
            System.out.println("时间:"+(end-start)+"sum"+"/n"+sum);
    
        }
        public static void test2() throws ExecutionException, InterruptedException {
            Long start=System.currentTimeMillis();
            ForkJoinPool forkJoinPool=new ForkJoinPool();
            ForkJoinTask<Long> task = new FaskJoinTest(0L, SUM);
            ForkJoinTask<Long> submit = forkJoinPool.submit(task);  //提交 有return
            Long aLong = submit.get();
            System.out.println(aLong);
            Long end=System.currentTimeMillis();
            System.out.println("时间:"+(end-start));
    
        }
        public static void test3(){
           // 流式计算 未来的佼佼者
            Long start=System.currentTimeMillis();
            long reduce = LongStream.range(0L, 20_0000_0000).parallel().reduce(0, Long::sum);
            System.out.println(reduce);
            Long end=System.currentTimeMillis();
            System.out.println("时间:"+(end-start));
    
    
        }
    }
    
    

    流式计算为什么那么快

    重点 因为是 并行执行 将cpu核数 资源使用到极致

    并发 并行 串行流 采用的无状态 操作放入 链表 然后在终结任务执行

    并行流 基本差不多 但是采用啦 forkjoin 分片处理

    异步回调

    Future 设计的初衷:对将来的某个事件结果进行建模!

    其实就是前端 --> 发送ajax异步请求给后端

    但是我们平时都使用CompletableFuture

    第一种没有返回值的 异步回调

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<Void> integerCompletableFuture =CompletableFuture.runAsync(()->{
    
            try {
                TimeUnit.SECONDS.sleep(3);
                System.out.println(Thread.currentThread().getName()+"A");
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        System.out.println("11111111111");
        Void unused = integerCompletableFuture.get();
    }
    

    第二种有返回值的 异步回调 成功或失败 类似于 success 200 error 404 500

     CompletableFuture<Integer> integerCompletableFuture =CompletableFuture.supplyAsync(
                    ()->{
                        System.out.println(Thread.currentThread().getName());
                        int i=10/0;
                        return 1024;
                    });
            System.out.println(integerCompletableFuture.whenComplete(
                    //异步 success函数回调
                    (t,s)->{
                        System.out.println("t="+t);
                        System.out.println("s="+s);
                    }
            ).exceptionally((e)->{
                System.out.println(e.getMessage());
                return 404;
            }).get());
    
    
        }
    }
    //输出
    ForkJoinPool.commonPool-worker-1
    t=null
    s=java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
    java.lang.ArithmeticException: / by zero
    404
    

    whenComplete: 有两个参数,一个是t 一个是u

    T:是代表的 正常返回的结果

    U:是代表的 抛出异常的错误信息

    如果发生了异常,get可以获取到exceptionally返回的值;

    JMM

    什么是Volatile

    Volatile是java虚拟机提供的轻量级同步机制

    • 保证可见性
    • 不保证原子性
    • 禁止指令重排序

    可见性概念

    立即将缓存中数据写会到内存中

    其他处理器通过嗅探总线上传播过来了数据监测自己缓存的值是不是过期了,如果过期了,就会对应的缓存中的数据置为无效。而当处理器对这个数据进行修改时,会重新从内存中把数据读取到缓存中进行处理。

    在这种情况下,不同的CPU之间就可以感知其他CPU对变量的修改,并重新从内存中加载更新后的值,因此可以解决可见性问题。

    什么是jmm

    jmm: java的内存模型 不存在的东西 概念 思想 约定

    关于jmm的一些同步约定

    1. 线程解锁前,必须把共享变量立刻刷新到主存储
    2. 线程加锁前 必须读取主存种的最新值到工作内存中
    3. 加锁和解锁是同一把锁

    线程 工作内存 主内存

    8种操作
    在这里插入图片描述

    在这里插入图片描述

    如果这样就会出现一个问题 线程B修改变量为flase 刷新到主存 但是线程A还在执行 flag=true 所以线程A此时获取的就不是最新变量

    jmm8种规定

    • lock(锁定):作用于主内存的变量,把一个变量标识为一条线程独占状态。
    • unlock(解锁):作用于主内存变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。
    • read(读取):作用于主内存变量,把一个变量值从主内存传输到线程的工作内存中,以便随后的load动作使用
    • load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中。
    • use(使用):作用于工作内存的变量,把工作内存中的一个变量值传递给执行引擎,每当虚拟机遇到一个需要使用变量的值的字节码指令时将会执行这个操作。
    • assign(赋值):作用于工作内存的变量,它把一个从执行引擎接收到的值赋值给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作。
    • store(存储):作用于工作内存的变量,把工作内存中的一个变量的值传送到主内存中,以便随后的write的操作。
    • write(写入):作用于主内存的变量,它把store操作从工作内存中一个变量的值传送到主内存的变量中。

    Java内存模型还规定了在执行上述八种基本操作时,必须满足如下规则:

    • 如果要把一个变量从主内存中复制到工作内存,就需要按顺寻地执行read和load操作, 如果把变量从工作内存中同步回主内存中,就要按顺序地执行store和write操作。但Java内存模型只要求上述操作必须按顺序执行,而没有保证必须是连续执行。
    • 不允许read和load、store和write操作之一单独出现
    • 不允许一个线程丢弃它的最近assign的操作,即变量在工作内存中改变了之后必须同步到主内存中。
    • 不允许一个线程无原因地(没有发生过任何assign操作)把数据从工作内存同步回主内存中。
    • 一个新的变量只能在主内存中诞生,不允许在工作内存中直接使用一个未被初始化(load或assign)的变量。即就是对一个变量实施use和store操作之前,必须先执行过了assign和load操作。
    • 一个变量在同一时刻只允许一条线程对其进行lock操作,但lock操作可以被同一条线程重复执行多次,多次执行lock后,只有执行相同次数的unlock操作,变量才会被解锁。lock和unlock必须成对出现
    • 如果对一个变量执行lock操作,将会清空工作内存中此变量的值,在执行引擎使用这个变量前需要重新执行load或assign操作初始化变量的值
    • 如果一个变量事先没有被lock操作锁定,则不允许对它执行unlock操作;也不允许去unlock一个被其他线程锁定的变量。
    • 对一个变量执行unlock操作之前,必须先把此变量同步到主内存中(执行store和write操作)。

    Volatile

    验证

    保证可见性

    public class VolatileTest {
        private volatile static int num=0;
    
        public  static void main(String[] args) {
            new Thread(()->{
                while (num==0){
    
                }
            }).start();
            try {
                TimeUnit.SECONDS.sleep(3);
    
            }catch (Exception e){
    
            }
            num=1;
            System.out.println(num);
        }
    }
    

    非原子性

    原子性 不可分割的

    public class Vtest2 {
        private volatile static  int num=0;
        public  static void add(){
            num++;  //本身就不是一个原子性操作  javap -c 项目名 (反编译操作)
        }
    
        public  static void main(String[] args) {
            for (int i = 1; i <10 ; i++) {
                new Thread(()->{
                    for (int j = 0; j <1000 ; j++) {
                       add();
                    }
                }).start();
            }
            System.out.println(Thread.activeCount()>2);
            Thread.yield();
            System.out.println(Thread.currentThread().getName()+num);
        }
    

    此时发现值还是会有问题 说明没有保证原子性

    可以加锁来保证 只不过那也比较耗费资源

    推荐使用原子类来处理

    通过原子类 提供原子性

    public class Vtest2 {
        private volatile static AtomicInteger num=new AtomicInteger();
        public  static void add(){
            num.incrementAndGet();  //相当于++操作 但是底层是调用啦 cpu的cas
            //本身就不是一个原子性操作  javap -c 项目名 (反编译操作)
        }
    
        public  static void main(String[] args) {
            for (int i = 1; i <10 ; i++) {
                new Thread(()->{
                    for (int j = 0; j <1000 ; j++) {
                       add();
                    }
                }).start();
            }
            System.out.println(Thread.activeCount()>2);
            Thread.yield();
            System.out.println(Thread.currentThread().getName()+num);
        }
    }
    

    指令重排

    什么是指令重排:你写的程序 并不是按照你写的那也去执行的;

    源代码–>编译器优化的重排–>指令并行也可能重排–>内存系统也会重排–>执行

    线程A 线程B
    x=b y=a
    a=1 b=2

    正常执行 应该是0

    线程A 线程B
    a=1 b=3
    y=b x=a

    指令重排的诡异操作 可能导致答案异常 y=3 x=1

    volatile 怎么保证防止指令重排序
    

    内存屏障,cpu指令 作用

    保证啦操作系统的执行顺序

    可以保证某些变量的内存可见性(利用了这些特性保证啦 volatile可见性)

    小结 volatile 是可以保持的 可见性。不能保证原子性,由于内存屏障 可以避免指令重排现象

    彻底玩转单例模式

    饿汉单例模式 会造成资源浪费

    /**
     * 饿汉式
     */
    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];
        
    
        public Hungry() {
        }
        private final static Hungry hungry=new Hungry();
    
        public static Hungry getInstance(){
            return hungry;
        }
    }
    

    DCL懒汉式

    二种防止反射破坏 策略

    双重锁检测

    通过定义标志位 加锁

    public class LazyMan {
        private static boolean flag=false;
        public LazyMan(){
            synchronized (LazyMan.class){
                if (flag==false){
                    flag=true;
                }else{
                    throw new RuntimeException("不要试图用反射搞我");
                }
            }
            System.out.println(Thread.currentThread().getName()+"ok");
    
        }
        /**
         * 1、分配内存空间
         * 2、执行构造方法,初始化对象
         * 3、把这个对象指向这个空间
         *就有可能出现指令重排问题
         *比如执行的顺序是1 3 2 等
         *我们就可以添加volatile保证指令重排问题
         */
        private volatile static LazyMan lazyMan;  //防止指令重排 而导致占用了空间 没初始化 返回未初始化对象
    
        public static LazyMan getInstance() throws Exception {
            //双重检测锁模式 简称DCL懒汉式 解决啦 多条线程进入的问题
                if (lazyMan==null) {
                synchronized (LazyMan.class) {
                    if (lazyMan == null) {
                         lazyMan = new LazyMan();
                        System.out.println(Thread.currentThread().getName() + "ok");
                    }
                }
            }
            return lazyMan;
        }
    
        public static void main(String[] args) throws Exception {
    //        for (int i = 0; i <10 ; i++) {
    //            new Thread(()->{
    //                LazyMan instance = LazyMan.getInstance();
    //            }).start();
    //        }
            //反射改变对象  获取构造器 来破坏单例模式
            Constructor<LazyMan> declaredConstructor = LazyMan.class.getDeclaredConstructor(null);
            Field flag = LazyMan.class.getDeclaredField("flag");
            flag.setAccessible(true);
    
            declaredConstructor.setAccessible(true); //无视私有构造器
            LazyMan lazyMan = declaredConstructor.newInstance();
            LazyMan lazyMan1 = declaredConstructor.newInstance();
            flag.set(lazyMan1,false);
    
    
            System.out.println(lazyMan);
            System.out.println(lazyMan1);
    
        }
    }
    

    静态内部类单例模式

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

    单例不安全, 因为反射

    /**
     * 枚举本身就是一个 class
     */
    public enum EnumTest {
        INSTANCE;
        public EnumTest getInstance(){
            return INSTANCE;
        }
    
        public static void main(String[] args) throws Exception {
            Constructor<EnumTest> declaredConstructor = EnumTest.class.getDeclaredConstructor(null);
            declaredConstructor.setAccessible(true);
            EnumTest enumTest = declaredConstructor.newInstance();
            EnumTest enumTest1 = declaredConstructor.newInstance();
            System.out.println(enumTest1==enumTest);
        }
    }
    

    此时报了个特别的错误

    Exception in thread "main" java.lang.NoSuchMethodException: com.hy.single.EnumTest.<init>()
    	at java.lang.Class.getConstructor0(Class.java:3110)
    	at java.lang.Class.getDeclaredConstructor(Class.java:2206)
    	at com.hy.single.EnumTest.main(EnumTest.java:15)
    

    并没有报enum 官方的防止反射错误 是为什么呢

    img

    =原来如此 我们都被idea骗了 通过反编译知道他默认不是无参 而是带有参数的 所以我们反射就会报main错误 真相大白

    public static EnumSingle[] values()
    {
        return (EnumSingle[])$VALUES.clone();
    }
    
    public static EnumSingle valueOf(String name)
    {
        return (EnumSingle)Enum.valueOf(com/ogj/single/EnumSingle, name);
    }
    
    private EnumSingle(String s, int i)
    {
        super(s, i);
    }
    
    public EnumSingle getInstance()
    {
        return INSTANCE;
    }
    
    public static final EnumSingle INSTANCE;
    private static final EnumSingle $VALUES[];
    
    static 
    {
        INSTANCE = new EnumSingle("INSTANCE", 0);
        $VALUES = (new EnumSingle[] {
            INSTANCE
        });
    }
    

    最终ok

    /**
     * 枚举本身就是一个 class
     */
    public enum EnumTest {
        INSTANCE;
        public EnumTest getInstance(){
            return INSTANCE;
        }
    
        public static void main(String[] args) throws Exception {
            Constructor<EnumTest> declaredConstructor = EnumTest.class.getDeclaredConstructor(String.class,int.class);
            declaredConstructor.setAccessible(true);
            EnumTest instance = EnumTest.INSTANCE;//这是原生对象
            EnumTest enumTest = declaredConstructor.newInstance(); //这是我们破坏的对象
            System.out.println(instance);
            System.out.println(enumTest);
        }
    }
    

    CAS深究

    修内功 才是本质 网络 系统 原理

    unsafe类 主要作用就是调用底层 native c++ 来调用内存
    在这里插入图片描述

    深入源码 探究底层 ++的由来

    在这里插入图片描述

    小结

    CAS 如果工作内存的值和主内存的值 是期望的 就会执行更新 否则不执行 内部加了自旋锁 如果不是就一直循环;

    CAS 缺点

    • 循环比较耗时
    • 一次性只能保证一个原子性
    • ABA问题

    CAS (ABA问题)

    假设有两个线程——线程1和线程2,两个线程按照顺序进行以下操作:

    (1)线程1读取内存中数据为A;

    (2)线程2将该数据修改为B;

    (3)线程2将该数据修改为A;

    (4)线程1对数据进行CAS操作

    在第(4)步中,由于内存中数据仍然为A,因此CAS操作成功,但实际上该数据已经被线程2修改过了。这就是ABA问题。

    private static  AtomicInteger atomicInteger=new AtomicInteger(2020);
    
      public static void main(String[] args) {
          //expect 期望  update更新   概念 如果达到期望值就更新 否则 不更新
          System.out.println(atomicInteger.compareAndSet(2020, 2021));
          System.out.println(atomicInteger.get());
          //捣乱修改过的线程
          System.out.println(atomicInteger.compareAndSet(2021, 2020));
          System.out.println(atomicInteger.get());
    
          System.out.println(atomicInteger.compareAndSet(2020, 6666));
          System.out.println(atomicInteger.get());
    
    
      }
    

    原子引用(对应是思想 乐观锁)

    在这里插入图片描述

    关键注意点

    使用这个解决ABA问题

    public static void main(String[] args) {
        /**
         * 大坑 如果使用的是包装类型 就要注意引用类型啦
         * 值过大 开辟新的内存空间 然后 == 比较引用地址值不一致 导致false
         */
        AtomicStampedReference <Integer> atomicStampedReference=new AtomicStampedReference<Integer>(1,1);
        new Thread(()->{
            int stamp = atomicStampedReference.getStamp();
            System.out.println("a1=>"+stamp);
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (Exception 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();
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("b1=>"+stamp);
            System.out.println(atomicStampedReference.compareAndSet(1, 3, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1));
            System.out.println("b2=>"+atomicStampedReference.getStamp());
        },"B").start();
    
    }
    

    各个锁的理解

    可重入锁 概念 只有进了一个锁 里面就等于都获取 就等于 进大门 等于卧室门也能进入

    公平锁, 非公平锁

    public ReentrantLock(boolean fair) {  //FALSE 就是公平
        sync = fair ? new FairSync() : new NonfairSync();
    }
    

    公平锁: 非常公平,先来后到,不允许插队

    非公平锁: 非常不公平, 允许插队

    img

    synchronized

    //实际上是一把锁
        public static void main(String[] args) {
            Phone phone=new Phone();
         new Thread(()->{
             System.out.println(Thread.currentThread().getName());
             phone.sms();
         },"A").start();
    
            new Thread(()->{
            System.out.println(Thread.currentThread().getName());
                phone.sms();
         },"B").start();
    
        }
    }
    class Phone{
        public  synchronized void sms(){
            System.out.println("发短信");
            call();
        }
        public  synchronized void call(){
            System.out.println("打电话");
        }
    }
    

    lock版 可重入锁

    public static void main(String[] args) {
            Phone1 phone=new Phone1();
            new Thread(()->{
    
                System.out.println(Thread.currentThread().getName());
                phone.sms();
            },"A").start();
    
            new Thread(()->{
                System.out.println(Thread.currentThread().getName());
                phone.sms();
            },"B").start();
    
        }
    
    
    }
    class Phone1{
        private static Lock lock=new ReentrantLock();
        public   void sms(){
            lock.lock();
            try {
                System.out.println("发短信");
                call();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
        public  void call(){
            lock.lock();
            try {
                System.out.println("打电话");
    
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
    

    细节 锁必须匹配 否则很容易deadlock

    自旋锁 SpinLock

    在这里插入图片描述

    底层

     AtomicReference<Thread> atomicReference=new AtomicReference<Thread>();
    
    //自定义自旋锁
        //加锁
    public void myLock(){
        Thread thread = Thread.currentThread();
        System.out.println(Thread.currentThread().getName()+"==>myLock");
        //自旋锁  底层Cas
        while (!atomicReference.compareAndSet(null,thread)){
    
        }
    
    }
    //解锁
    public void myUnLock(){
        Thread thread = Thread.currentThread();
        System.out.println(Thread.currentThread().getName()+"==>myUnLock");
        atomicReference.compareAndSet(thread,null);
    
    }
    
      public static void main(String[] args) {
            //原始锁
    //        ReentrantLock reentrantLock = new ReentrantLock();
    //        reentrantLock.lock();
    //        reentrantLock.unlock();
    
            //用自己的写的自旋锁
            SpinLockDemo lockDemo = new SpinLockDemo();
            new Thread(()->{
                lockDemo.myLock();
                try {
                    TimeUnit.SECONDS.sleep(5); //这里就会走自旋锁 会一直循环
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lockDemo.myUnLock();
                }
    
            },"t1").start();
            new Thread(()->{
                lockDemo.myLock();
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lockDemo.myUnLock();
                }
    
            },"t2").start();
        }
    

    互斥

    占有等待

    循环等待

    不可抢占

       public static void main(String[] args) {
             String lockA = "lockA";
             String lockB = "lockB";
    
            new Thread(new MyThead(lockA,lockB),"t1").start();
            new Thread(new MyThead(lockB,lockA),"t2").start();
        }
    }
    class MyThead implements Runnable {
        private String lockA ;
        private String lockB;
    
        public MyThead(String lockA, String lockB) {
            this.lockA = lockA;
            this.lockB = lockB;
        }
    
        @Override
        public void run() {
            synchronized (lockA) {
                System.out.println(Thread.currentThread().getName() + "lock" + lockA + "get=>" + lockB);
                try {
                    TimeUnit.SECONDS.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lockB) {
                    System.out.println(Thread.currentThread().getName() + "lock" + lockB + "get=>" + lockA);
    
                }
            }
        }
    }
    

    死锁排查解决

    jps -l 查看当前信息

    在这里插入图片描述

    用jstack + 类编号 查看堆栈

    在这里插入图片描述

    面试问 怎么排查问题 日志log 看堆栈

    展开全文
  • 问题4-4:在文献中有时会见到对等连网(peer-to-peer networking),这是什么意思? 问题4-5:在一个互联网中,能否使用一个很的交换机(switch)来代替互联网中很多的路由器? 问题4-6:为什么IP地址又称为“虚拟...
  • CORBA企业解决方案

    2019-01-25 16:16:50
    这种理解实际集中在如接口定义、安全性、实体命名、事务、通信选择、两层或体系结构、数据库集成、容错性、系统管理等领域。用户如果对自己系统中重要的方面有着深刻的理解,那么就能更快更好地实现该系统。...
  • 问题6-4:在文献中有时会见到对等连网(peer-to-peer networking),这是什么意思? 问题6-5:在一个互连网中,能否使用一个很的交换机(switch)来代替互连网中很多的路由器? 问题6-6:为什么IP地址又称为“虚拟...
  • 区块链环境安装

    2021-05-12 14:31:11
    什么是区块链?从科技层面来看,区块链涉及数学、密码学、互联网和计算机编程等很多科学技术问题。从应用视角来看,简单来说,区块链一个分布式的共享账本和数据库,具有去中心化、不可篡改、全程留痕、可以追溯...
  • 主要功能点:高安全性的用户管理体系、高安全性的异构系统数据导入导出、拼音检索、复合检索、无限级次数据管理、个性化邮件群发、Excel文件导入导出。 技术点 ADO.Net技术应用、SQLServer、MD5安全算法、基于NPOI的...
  • MAC地址通常硬件自带的,由网卡生产商来分配的,而且已经固化到了网卡中去,一般来说不可更改的。而IP地址则通常由网络管理员或系统自动分配。 (3)传统的交换机只能分割冲突域,不能分割广播域;而路由器可以...
  • 多线程的三大特性(原子性、可见性和有序性) 浅谈AQS中的CountDownLatch、Semaphore与CyclicBarrier 浅谈AQS中的Lock与Condition 一个工作了7年的朋友去面试竟然被Thread类虐的体无完肤 如何使用Java7中提供的Fork/...
  • 主要功能点:高安全性的用户管理体系、高安全性的异构系统数据导入导出、拼音检索、复合检索、无限级次数据管理、个性化邮件群发、Excel文件导入导出。 技术点 ADO.Net技术应用、SQLServer、MD5安全算法、基于NPOI的...
  • 上面的Refresh方案虽然可以解决单个微服务运行期间重载配置信息的问题,但是在真正的实践生产中,可能会有N多的服务需要更新配置,如果每次依靠手动Refresh将一个巨大的工作量,这时候Spring Cloud提出了另外一个...

空空如也

空空如也

1 2 3 4 5
收藏数 89
精华内容 35
关键字:

安全生产三大体系是什么