Collections.sort 引起的线程不安全操作
Collections.sort 引起的线程不安全操作测试场景12345678910111213141516171819202122232425262728293031public static void main(String [] args) throws Exception { //快递优先级对于所有线程来说是一个全局变量 List<String> list = new ArrayList<>(); list.add("A"); list.add("D"); list.add("C"); list.add("B"); list.add("F"); list.add("E"); Runnable runnable = new Runnable() { @Override public void run() { //这里对一个 ...
Springboot 程序正常退出问题
Springboot 程序正常退出问题场景通过 jenkins 调用 springboot 任务,任务执行完成之后,jenkins 没有收到任务结束信号,导致定时任务无法多次执行。
分析
去掉业务调用逻辑,测试程序是否正常退出
1234567891011121314ConfigurableApplicationContext applicationContext = SpringApplication .run(SurfContentSyncApplication.class, args);try { log.info("surf-content-sync success!!!"); //HotVideoSyncService bean = applicationContext.getBean(HotVideoSyncService.class); //bean.doSyncHotVideo(); } catch (Throwable e) { log.error("error", ...
多线程(五 ) JUC常用工具
Condition的使用1234567891011121314151617181920212223242526public class ConditionWait implements Runnable{ private Lock lock; private Condition condition; public ConditionWait(Lock lock, Condition condition) { this.lock = lock; this.condition = condition; } @Override public void run() { System.out.println("begin condition-wait"); try { lock.lock(); condition.await(); System.out.print ...
多线程(五 ) Thread.join方法详解
案例分析
案例1
12345678910111213141516171819202122232425262728public class JoinTest1 extends Thread{ public void run(){ System.out.println(Thread.currentThread().getName()+":begin"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+":end"); } public static void main(String[] args) throws Int ...
多线程(四 ) Lock的使用及原理
Lock 的使用我们知道 synchronize 关键字可以实现线程安全,这个是 jvm 层面帮我们实现的线程安全操作。而 lock 是在 jdk 层次实现的线程安全,那么 lock 怎么使用呢。
ReentrantLockReentrantLock:可重入锁,支持重入。简单意思上来说,就是当线程 1 拿到锁的时候,线程 1 进入同一把锁的其他方法的时候,可以直接进入,增加重入次数。
ReentrantLock 的使用
创建一个 Lock 对象。调用 lock 方法加锁,下面执行的代码都在同步代码块调用 unlock 方法,释放锁资源。
123456789101112131415161718192021222324252627282930public class ReentrantLockDemo { private static int count = 0; static Lock lock = new ReentrantLock(); public static void inc(){ lock.lock(); ...
多线程(三) volatile原理分析
案例分析
案例 1
12345678910111213141516171819202122232425262728293031public class VolatileDemo { private static Boolean flag = false; public static void main(String[] args) throws InterruptedException { Thread threadA = new Thread(() -> { while (true) { if (flag) { System.out.println("线程:" + Thread.currentThread().getName()); break; } } }, ...
多线程(二) synchronized分析
synchronized 的使用为了充分利用 cpu 资源,我们经常会使用多线程来合理的利用 cpu 空闲资源。但是在使用多线程的时候,由于多个线程存在对内存中对象的拷贝,当多个线程对一个资源进行访问的时候,会出现线程不安全的情况。为了避免这种线程不安全的情况 ,jdk 提供了 synchronied 的方式来保证同步代码块的安全问题。
synchronid 的加锁有 2 种类型,分别为对象锁和类锁。
对象锁
1234567891011public synchronized void method1(){ while (true){ try { TimeUnit.SECONDS.sleep(1); System.out.println("当前线程:"+Thread.currentThread().getName()+" 开始工作。"); } catch (InterruptedException e) { e.printStackTrace(); ...
多线程(一) 线程的基本知识
线程和进程进程:操作系统资源资源分配的基本单位,占用的资源较大,进程间无共享内存,切换进程时,cpu 消耗太多
线程:任务调度和执行的基本单位,一个进程可以有多个线程,线程之间公用所在进程的内存,资源共享。创建线程的开销较小。
线程的生命周期
线程总共有 6 种状态,分别如下:
新建状态(NEW):当创建一个线程对象的时候,线程处于该状态。
运行状态(RUNABLE):当调用线程的 start 方法时,线程处于该状态。该状态下有 2 个不同的子状态,分别是可运行和运行状态,当 cpu 调度当前线程的时候,线程状态为可运行状态,当 cpu 放弃当前线程或者当前线程执行 yield 操作时,该线程会重新进入可运行状态,等待 cpu 调度。
等待状态(WAITING 和 TIME_WAITING):两个状态唯一的区别就是是否加上时间参数,通过调用 sleep,join,wait 等方法进入该状态。
阻塞状态(BLOCKED):只有在执行到 synchronized 代码块,没有获取到锁的时候,会变成阻塞状态。
结束状态(TERMINATED):当前线程执行结束。
线程的创建方式 ...
Spring源码分析(4)-SpringMVC的实现过程
SpringMVC 的实现过程SpringMVC 的实现过程主要分为 2 个步骤,初始化阶段和调用阶段
初始化阶段,这个阶段主要是在 DispatcherServlet 初始化的时候调用,完成组件的初始化
调用阶段,这个阶段主要体现在请求过来的时候,通过 doDispatch 方法来完成调用
具体实现时序图如下:
具体分析
首先我们知道 SpringMVC 的实现过程主要是通过 DispatcherServlet 来实现的,因为它一个 Servlet,那么必将遵守 Servlet 的生命周期,初始化调用 init 方法,我们在 DispatcherServlet 没有找到,然后往它的父类寻找,结果发现在它的祖父类里面找到对应的 init 方法
12345678910111213141516171819202122232425262728293031public final void init() throws ServletException { if (logger.isDebugEnabled()) { logger.debug("In ...
Spring源码分析(3)-AOP 实现过程
首先给出 AOP 的实现过程的时序图Spring 的 AOP 实现大致可以分为 2 个步骤
1.创建代理对象。这个阶段主要为代理对象的创建,封装好对应的 advise 集合
2.调用阶段,在调用阶段完成 aop 的功能
过程分析
创建代理对象分析
在上一篇博客中,我们有分析 DI 的实现过程,那么在实现 DI 的过程中,其实包含了对应的 AOP 过程,我们追踪到 AbstractAutowireCapableBeanFactory 的 creatBean 方法中,在调用 createBeanInstance 创建 bean 实例,populateBean 注入对应的属性之后,调用了 initializeBean 方法,这个方法就是 AOP 的创建代理对象的入口
initializeBean 方法的具体代码如下
12345678910111213141516171819202122232425262728293031323334protected Object initializeBean(final String beanName, final Object bean, @Nu ...