ICO容器的结构如上图所示,首先要让IOC容器去读取Bean的配置信息,并在容器中生成一份相应的Bean定义注册表,根据这张注册表去实例化Bean,装配好Bean之间的依赖关系,为上层提供准备就绪的环境,Spring提供一个配置文件描述Bean还有Bean之间的依赖关系,利用Java语言的反射功能实例化Bean并建立Bean之间的依赖关系。
一枚野生程序员~
ICO容器的结构如上图所示,首先要让IOC容器去读取Bean的配置信息,并在容器中生成一份相应的Bean定义注册表,根据这张注册表去实例化Bean,装配好Bean之间的依赖关系,为上层提供准备就绪的环境,Spring提供一个配置文件描述Bean还有Bean之间的依赖关系,利用Java语言的反射功能实例化Bean并建立Bean之间的依赖关系。
SpringIOC是Spring Core最核心的部分,要了解控制反转(Inversion of Control),我觉得有必要先了解软件设计的一个重要思想:依赖倒置原则。
1、高层模块不应该依赖底层模块,二者都应该依赖抽象
2、抽象不应该依赖细节,细节应该依赖抽象。
3、依赖倒置的中心思想是面向接口编程。
4、依赖倒置原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础搭建的架构要稳定的多。
5、使用接口或抽象类的目的是指定好规范,而不涉及任何具体操作,展现细节的任务交给他们的实现类来完成。
本篇文章主要记录了JUC的四个并发工具类,闭锁CountDownlatch、栅栏CyclicBarrier、信号量Semaphore、交换器Exchanger。CountDownlatch通常用于主线程等待其他任务线程执行完毕的场景;CyclicBarrier主要阻塞当前线程,等待其他线程(大家无论谁先跑到A点,必须要等其他线程也到达了A点,大家才能继续)。信号量Semaphore可以用来控制同时访问特定资源的线程数量(比如100个线程只能有10个线程可以获得MySQL连接)。交换器Exchanger很少用,只适用于两个线程在同步点交换数据的场景(如下图)。
Fork/Join框架就是在必要的情况下,将一个大任务,进行拆分(fork)成若千个小任务(拆到不可再拆时),再将一个个的小任务运算的结果进行join汇总。
ForkJoin框架采用工作窃取
模式(work-stealing) :当执行新的任务时它可以将其拆分分成更小的任务执行,并将小任务加到线程队列中,然后再从一个随机线程的队列中偷一个并把它放在自己的队列中。
相对于一般的线程池实现,fork/join框架的优势体现在对其中包含的任务的处理方式上,在一般的线程池中,如果一个线程正在执行的任务由于某些原因无法继续运行,那么该线程会处于等待状态。而在fork/join框架实现中,如果某个子问题由于等待另外一个子问题的完成而无法继续运行。那么处理该子问题的线程会主动寻找其他尚未运行的子问题来执行。这种方式减少了线程的等待时间,提高了性能。
本文通过生产者消费者模型主要讲述了什么是虚假唤醒,以及处理处理虚假唤醒。另外还使用了Condition 来控制线程间的通信,Condition接口描述了可能会与锁有关联的条件变量,这些变量在用法上与使用Object.wait 访问的隐式监视器类似,但提供了更强大的功能。需要特别指出的是,单个Lock 可能与多个Condition 对象关联。为了避免兼容性问题,Condition 方法的名称与对应的Object 版本中的不同。 在Condition 对象中,与wait、notify 和notifyAll 方法对应的分别是await、signal 和signalAll。 Condition允许发生虚假唤醒,这通常作为对基础平台语义的让步。不过Condition还是应该总是在一个循环中被等待,避免虚假唤醒的发生。
本文主要讲述了使用线程池的好处,Executors创建的五种线程池特点,简单介绍了Fork/Join框架。围绕Executor框架展开,阐述了线程池的工作流程,探讨了ThreadPoolExecutor的全部构造参数和意义,以及阿里巴巴不推荐使用Executors创建线程池的原因,另外,介绍了我们应该怎么样合理的创建线程池,对于CPU密集型和IO密集型以及混合型的创建方式。探讨了新任务提交后的执行流程,另外简单画了一下线程池生命周期图。
Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或者并发执行任务的程序都可以使用线程池。开发
中使用线程池的三个优点如下:
1、降低资源消耗:通过重复利用已创建的线程降低线程创建和销毁带来的消耗。
2、提高响应速度:当任务到达时,任务可以不需要等待线程创建就能立即执行。
3、提高线程的可管理性:使用线程池可以统一进行线程分配、调度和监控。
我们在使用锁时,线程获取锁是一种悲观锁策略,即假设每一次执行临界区代码都会产生冲突, 所以当前线程获取到锁的时候同时也会阻塞其他线程获取该锁。而CAS操作(又称为无锁操作)是一种乐观锁策略,它假设所有线程访问共享资源的时候不会出现冲突,既然不会出现冲突自然而然就不会阻塞其他线程的操作。因此,线程就不会出现阻塞停顿的状态。那么,如果出现冲突了怎么办?无锁操作是使用CAS(compare and swap)又叫做比较交换来鉴别线程是否出现冲突,出现冲突就重试当前操作直到没有冲突为止。
synchronized和ReentrantLock的区别
先说说synchronized和ReentrantLock的区别吧,AQS的分析得等两天了:
1、ReentrantLock (再入锁),位于java.util.concurrent.locks包
2、和CountDownLatch、Future Task、Semaphore一样基于AQS实现
3、能够实现比synchronized更细粒度的控制,如控制公平与非公平
4、调用lock()之后,必须调用unlock()释放锁
5、性能未必比synchronized高,并且也是可重入的
6、synchronized是关键字,ReentrantLock是类
7、ReentrantLock可以对获取锁的等待时间进行设置,避免死锁的发生
8、ReentrantLock可以获取各种锁的信息
9、ReentrantLock可以灵活地实现多路通知
10、机制:sync操作Mark Word,lock调用Unsafe类的park()方法
本文主要讲述了synchronized的实现原理,还有synchronized的优化。其中主要包括了自适应自旋,锁消除、锁粗化、以及偏向锁和轻量级锁。另外阐述了锁的内存语义和对三种锁的总结。其实工程学科就是不断解决实际问题才能得以发展,synchronized从早期的一上来就直接使用Mutex逐步优化到现在的程度,mutex互斥量是最重要的同步原语,但是我们去使用mutex的时候却会出现诸多问题(比如销毁了已加锁的互斥量、死锁问题)Monitor机制是编程语言在语法上提供的语法糖,假设我们用的是C语言,那么很明显无法使用Monitor机制。
很多文章笼统的说synchronized是基于Monitor机制实现的,我认为这是错误的说法,Monitor 机制必须要有临界区、Monitor对象和互斥量、条件变量和wait()、signal()等要素。在synchronized的实现中根本找不到所有对应的元素。我认为Java的Monitor机制包括了synchronized、Object和程序员自己定的条件变量等(因为我们通常使用wait()、 notify()、notifyAll()配合synchronized才能取解决生产者消费者问题),这才一套完整的Monitor机制。JVM的ObjectMonitor用来辅助Java实现Monitor机制,直接把JVM的ObjectMonitor当成Monitor机制是不可取的。
tag:
缺失模块。
1、请确保node版本大于6.2
2、在博客根目录(注意不是yilia-plus根目录)执行以下命令:
npm i hexo-generator-json-content --save
3、在根目录_config.yml里添加配置:
jsonContent: meta: false pages: false posts: title: true date: true path: true text: false raw: false content: false slug: false updated: false comments: false link: false permalink: false excerpt: false categories: false tags: true