一、 前言 前面讲解过Java中线程池ThreadPoolExecutor原理探究,ThreadPoolExecutor是Executors中一部分功能,下面来介绍另外一部分功能也就是ScheduledThreadPoolExecutor...的实现,后者是一个可以在一定延迟时候或者定时进行任务调度的线程池。...ClassDiagram1.jpg Executors其实是个工具类,里面提供了好多静态方法,根据用户选择返回不同的线程池实例。...ScheduledThreadPoolExecutor继承了ThreadPoolExecutor并实现ScheduledExecutorService接口,关于ThreadPoolExecutor的介绍可以参考...,然后线程池线程会从阻塞队列获取超时的元素任务进行处理,下面看下队列元素如何实现的。
刚刚看了一下synchronized和volatile的区别,这里做一下笔记。 多线程中内存是如何分配的? 分为主内存和线程内存,当线程与其他线程共享一个变量时,便会把主内存的变量复制到线程内存中去。...Synchronized实现可见性 JMM对Synchronized规定: 线程加锁时,将清空线程内存中共享变量的值,从而使用共享变量时从主内存中重新读取新值。...线程解锁前,必须把共享变量的最新值刷新到主内存中。...线程执行互斥代码过程: 1、 获得互斥锁 2、 清空线程内存 3、 从主内存中拷贝最新副本到线程内存 4、 执行代码 5、 将更改后的变量刷新到主内存 6、 释放互斥锁 指令重排序:代码书写的顺序和实际执行的顺序不同...java编译器保证as-if-serial,但是在多线程程序中并不能保证顺序执行。
最近在看《Java并发编程实战》,并发方面的知识,今天看到了对象的可见性,在这里分享一下。 ...在单线程环境中,如果向某个变量写入值(比如全局变量),在没有其他操作写入的情况下,总是能得到想要的值(因为在单线程环境中是线程安全的)。但是如果在多线程环境中,这个情况就会被打破。...因为我们在执行某一线程的读操作的时候,其实并不知道是否有其他线程正在进行写操作,所以我们上面说到的可见性就在这里展开命题,我读操作的时候要知道另一个线程在写操作,这就是线程的安全性。...而且如果有一个读线程的操作的时候,我们给number赋值了42,但是它可能得到的仍然是0这个失效值,这里只是int类型的读取错误,如果我们在要求很严的环境中,读到一个失效的引用对象,这个对象的后续操作不可操作...而且Volatile 并不足以保证比如 i++这类递增操作的安全性,而是常用来表示某个操作完成或者是结束的状态标识符。 加锁机制可以确保可见性和原子性。而Volatile 只确保可见性。
引出Java多线程——synchronized、volatile 保障可见性synchronized、volatile 保障可见性原子性:在一次或者多次操作时,要么所有操作都被执行,要么所有操作都不执行...可见性:当一个线程对共享变量进行修改后,另外一个线程可以立即看到该变量修改后的最新值。有序性:程序执行的顺序按照代码的先后顺序执行。...执行代码 将修改后的副本的值刷新回主内存中 线程释放锁解决2:volatile 也可以保证多线程之间访问共享变量时的可见性。...flag的值还没有写会主内存 此时main方法main方法读取到了flag的值为false 当子线程t将flag的值写回去后,失效其他线程对此变量副本 再次对flag进行操作的时候线程会从主内存读取最新的值,放入到工作内存中总结...: volatile保证不同线程对共享变量操作的可见性,也就是说一个线程修改了volatile修饰的变量,当修改写回主内存时,另外一个线程立即看到最新的值。
可见性 一个线程对主内存的修改可以及时被其它线程观察到 导致共享变量在线程间不可见的原因 线程交叉执行 指令重排序加上线程交叉执行 共享变量更新后的值没有在工作内存与主存间及时更新 保证可见性和原子性...对于可见性Java提供了synchonized和volatile volatile 通过加入内存屏障和禁止重排序优化来实现,保证可见性不保证原子性 对volatile变量进行写操作时,会在写操作后加入一条...,两个线程同时执行到第一步(从内存中读取最新值)得到一样的最新的结果,然后进入第二步(+1操作)并进行第三步(从新写回主存)。...尽管第一步获取的值是一样的,但是同时将+1后的操作写回主存,这样就会丢掉某个+1的操作,这样就会出现线程不安全问题 总结 volatile进行多线程加是线程不安全的,不适合计数 volatile不具备原子性...volatile的使用场景 对变量的写操作不依赖当前值 该变量没有包含在其它变量的不变式子中 volatile适合作为状态的标记量 volatile boolean flag = false; //
Java内存模型 JMM(Java Memory Model,简称JMM)描述了Java程序中各种变量(线程共享变量)的访问规则,以及在JVM中将变量存储到内存和从内存中读取出变量这样的底层细节。...不同线程之间无法直接访问其他线程工作内存中的变量,线程间变量的传递需要通过主内存来完成 共享变量可见性实现的原理 线程1对共享变量的修改要想被线程2及时看到,必须经过如下2个步骤: 把工作内存1中更新过的共享变量刷新到主内存中...将主内存中最新的共享变量的值更新到工作内存2中 Java的内存模型: ?...Java语言层面支持的可见性实现方式有以下两种: synchronized volatile synchronized JMM关于synchronized的规定: 线程解锁前,必须把共享变量的最新值刷新到主内存中...多线程的有序性 在Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。
要了解Java内存模型,首先要了解什么是内存模型,之间在CPU缓存和内存屏障 中我们了解到缓存一致性问题以及处理器优化的指令重排序问题。为了保证并发编程中可以满足原子性、可见性及有序性。...目的是保证并发编程场景中的原子性、可见性和有序性。...可见性问题 可见性:主要是指一个线程对共享变量的写入可以被后续另一个线程读取到,也就说一个线程对共享变量的操作对另一个线程是可见的。...而可见性问题就是指一个线程对共享变量进行了写入而其他的线程却无法读取到该线程写入的结果,根据以下工作内存的缓存的模型我们可以知道,造成可见性的问题主要有两方面,一个是数据在写入的时候只是写入了缓存而没有写入主内存...可见性问题的解决方法 — volatile关键字 volatile关键字可以保证一个线程对共享变量的修改,能够及时的被其他线程看到。
就是通过可重入锁的保护并行对共享变量进行自增。 突然想到一个问题:共享变量 count 没有加 volatile 修饰,那么在并发自增的过程当中是如何保持内存立即可见的呢?...JMM 定义了线程和内存之间底层交互的语义和规范,比如多线程对共享变量的写 / 读操作是如何互相影响。...对于早期的 Intel386 处理器,保证了内存底层读写顺序和代码保持一致,我们称之为 program ordering,即代码中的内存读写顺序就限定了处理器和内存交互的顺序,所见即所得。...也就是线程 A 修改了 volatile 变量,那么线程 B 随后的读取一定是最新的值。...总结 针对本文开头提出的内存可见性问题,有着一系列的技术依赖关系才得以实现:count++ 可见性 → volatile 的 happens-before 原则 → volatile 底层 LOCK prefix
学习目标: 可见性介绍: synchronized实现可见性原理: 优化之后更加符合处理器的特点 synchronized实现可见性代码: 先附上代码: public...:" + result); } //内部线程类 private class ReadWriteThread extends Thread { //根据构造方法中传入的...volatile实现可见性: volatile不能保证原子性: 使用ReentrantLock同步 import java.util.concurrent.locks.Lock; import...Java编译器也会根据内存屏障的规则禁止重排序。...有的处理器的重排序规则较严,无需内存屏障也能很好的工作,Java编译器会在这种情况下不放置内存屏障。 为了实现JSR-133的规定,Java编译器会这样使用内存屏障。
} ③ 启动线程的操作与线程中的第一个操作同步 ④ 对于每个属性写入默认值(0,false,null)与 每个线程对其操作的同步 ⑤ 线程T1的最后操作与线程T2发现线程T1已经结束同步(isAlive...② 原则 同一个线程里面对数据做了变动,后面的动作可以及时的看到,其实还是可见性。 某个monitor上的unlock动作 happens-before 同一个monitor上后续的lock动作。...在某个线程对象上调用start() 方法 happens-before 该启动了的线程中的任意动作。...某个线程中的所有动作 happens-before 任意其他线程成功从该线程对象上的join() 中返回。...(九) final 在JMM中的处理 ① final在该对象的构造函数中设置对象的字段,当线程看到该对象时,将始终看到该对象的final字段的正确构造版本。
因为无法获知线程2对共享变量running做出的修改, 然后线程1一直处在运行状态。 这里简单说明一下Java Mememory Model简称JMM: ? ...在本例中线程2实际上是修改了自己本地内存中的running值, 但是并没有刷新到主内存中,线程1也一直在读自己本地内存中的值,并没有去主内存中重新获取。 ...为了让例子最终能输出 Thread 1 finished 方法:很简单, 直接设置变量running为volatile,以保证其在多线程环境中的内存可见性问题。 ...测试synchronized关键字对可见性的影响: 为了套用Happen-Before规则,这里直接在get()和doSetTrue()方法上加synchronized 也能保证可见性问题。...JMM关于synchronized的两条规定: 线程解锁前,必须把共享变量的最新值刷新到主内存中 线程加锁时,将清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中重新读取最新的值
《Java并发编程实战》书中给出定义:当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在调用代码中不需要任何额外的同步,这个类都能表现出正确的行为,那么这个类就是线程安全的...可见性 简单划下重点: 什么是线程间的可见性? 一个线程对共享变量值的修改,能够及时的被其他线程看到。 什么是共享变量?...(Java Memory Model,简称JMM) JMM描述了java程序中各种变量(线程共享变量)的访问规则,以及在JVM中将变量存储到内存和从内存中读取出变量这样的底层细节。...对于线程可见性大家更多层面是基于Volatile的应用,请大家移步我的另一篇文章【Java线程】深入理解Volatile关键字和使用 有序性 有序性是指程序在执行的时候,程序的代码执行顺序和语句的顺序是一致的...向每一位正在努力的程序员致敬!!! 参考资料 《Java高并发编程实战》 《Java并发编程》 多线程安全性和Java中的锁
在开发多线程时,可以用ThreadGroup关键字创建一个线程组来方便管理一系列的子线程,线程组可以统一的设置线程的某些属性。 ? ? ? ?...在使用上和正常操作线程一样没什么区别,但有时我们的确会用到线程组。...例如如果我们要将某些线程设置为守护线程的话,那我们只需要设置这个线程所在的线程组就可以了,那么这个线程组里的线程就统统都成了守护线程。 ? ? ? ?
所谓重入锁,指的是以线程为单位,当一个线程获取对象锁之后,这个线程可以再次获取本对象上的锁,而其他的线程是不可以的。 synchronized 和 ReentrantLock 都是可重入锁。...可重入锁的意义在于防止死锁。 可重入锁简单演示 什么是 “可重入”,可重入就是说某个线程已经获得某个锁,可以再次获取锁而不会出现死锁。...,当当前线程调用A类的对象methodA1同步方法,如果其他线程没有获取A类的对象锁,那么当前线程就获得当前A类对象的锁, 然后执行methodA1同步方法,方法体中调用methodA2同步方法,当前线程能够再次获取...A类对象的锁,而其他线程是不可以的,这就是可重入锁。...可重入锁的概念和设计思想大体如此,Java中的可重入锁ReentrantLock设计思路也是这样。 synchronized和ReentrantLock 都是可重入锁。
1.2 线程 多线程扩展了多进程的概念,使得一个进程可以同时并发处理多个任务,线程也被称为轻量级进程。就像进程在操作系统中的地位一样,线程在进程中也是独立的、并发的执行流。...当进程被初始化后,主线程就被创建了,对于Java程序来说,main线程就是主线程,我们可以在该进程中创建多条顺序执行路径,这些独立的执行路径都是线程。 ...如果此时有多个任务同时执行的需求,那么选择创建多进程的方式势必耗时费力,创建多个线程则要简单的多。 2、线程的创建和启动 在java中可以通过java.lang.Thread类实现多线程。...2.1 继承Thread类 在java中,线程是Thread类的对象,如果要创建和启动自己的线程,那么就可以直接继承Thread类。...2.2 实现Runnable接口 java有单继承的限制,所以除了可以直接继承Thread类,java还提供了实现java.lang.Runnabke接口的方式来创建自己的线程类。
1、 线程中的主要方法 a) isAlive() 判断线程是否还活着,即线程是否未终止 b) getPriority() 获得线程的优先级 c) setPriority() 设置线程的优先级... d) Thread.sleep() 设置线程休眠的时间 e) jion() 把当前线程与该线程合并 f) yield() 让出CUP g) 线程的优先级 ...c) 推荐使用的是设置标志位 3、 线程的高级操作 a) wait() 使当前线程等待,直到被其线程唤醒 b) notify() 唤醒等待的线程 4、 实现同步的两种方式...Synchronized void method(){} 1、 Java多线程的实现主要有两个方式,一个是通过继承Thread类,一个是Runnable接口的实现。...//获取优先级 17 System.out.println("线程一的优先级为:"+td1.getPriority()); 18 19 //设置线程的优先级优先级的值为
java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程池。在开发过程中,合理使用线程池能够带来三个好处。 第一:降低资源消耗。...ThreadPoolExecutor采取上述步骤的总体设计思路,是为了在执行execute()方法时,尽可能的避免获取全局锁(那将会是一个严重的可伸缩瓶颈)。...) return; c = ctl.get(); } //如果线程数大于等于核心线程数或创建线程失败,则将当前任务放到工作队列中...java线程池提供了以下四种策略: AbortPolicy:直接抛出异常 CallerRunsPolicy:主线程执行这个任务 DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务...只要调用了这两个关闭方法中的任意一个,isShutdown方法就会返回true。当所有的任务都已关闭后,才表示线程池关闭成功,这时调用isTerminaed方法就会返回true。
使用线程池的好处 降低资源的消耗: 线程池通过重复利用线程中已存在的线程,从而降低了创建线程和销毁线程所造成的资源消耗。...如果核心线程里的线程都在执行任务,则进入下一个流程; 线程池判断工作队列是否已满,如果工作队列未满,则将任务添加到工作队列中,如果队列已满,则执行下一个流程; 线程池判断线程池是否已满,如果未满,则创建一个新的工作线程来执行任务...以下是java线程池框架提供的4中饱和策略: AbortPolicy(默认):直接抛出异常 CallerRunsPolicy:只用调用者所在线程来运行任务 DiscardOldestPolicy:丢弃对立中最近的一个任务...,并执行当前任务 DiscardPolicy:不处理,直接丢弃任务 除了以上4中策略,还可以实现RejectedExecutionHandler接口,来自定义饱和策略,如记录日志或者持久化存储不能处理的任务...线程池就使用了这种队列; DelayedWorkQueue:使用优先级队列实现的无界阻塞队列,ScheduledThreadPoolExecutor线程池使用了这种阻塞队列; SynchronousQueue
转载请以链接形式标明出处: 本文出自:103style的博客 Java并发编程的艺术笔记 并发编程的挑战 Java并发机制的底层实现原理 Java内存模型 Java并发编程基础 Java中的锁的使用和实现介绍...Java并发容器和框架 Java中的12个原子操作类介绍 Java中的并发工具类 Java中的线程池 Executor框架 ---- 前言 Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程池...上图4 ThreadPoolExecutor采取上述步骤的总体设计思路,是为了在执行execute()方法时,尽可能地避免获取全局锁(那将会是一个严重的可伸缩瓶颈)。...: 线程池中的线程执行任务分两种情况: 在execute()方法中创建一个线程时,会让这个线程执行当前任务。...在JDK 1.5中Java线程池框架提供了以下4种策略。 AbortPolicy:直接抛出异常。 CallerRunsPolicy:只用调用者所在线程来运行任务。
线程池 · 语雀 (yuque.com) 为什么要用线程池 在 HotSpot VM 的线程模型中,Java 线程被一对一映射为内核线程。...Java 在使用线程执行程序时,需要调用操作系统内核的 API,创建一个内核线程,操作系统要为线程分配一系列的资源;当该 Java 线程被终止时,这个内核线程也会被回收。...Java 中 BlockingQueue 类型的队列也有很多,比如:(共 8 个) ArrayBlockingQueue:基于数组结构的有界阻塞队列 LinkedBlockingQueue:基于链表结构的阻塞队列...------ 除了使用以上 Java 线程池框架提供的拒绝策略之外,我们还可以自定义拒绝策略。...· 语雀 (yuque.com) Java中的线程池——如何创建及使用Executors的四种线程池-极客时间 (geekbang.org) 深入浅出 Java Concurrency (30): 线程池