Java并发学习4【面试+工作】 九.fork&join Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架 其中Vector(同步的ArrayList)和Stack(继承自Vector,先进后出)、HashTable(继承自Dictionary,实现了Map接口)是比较老的容器,Thinking in Java 并发容器 由上面的分析我们知道,同步容器并不能保证多线程安全,而并发容器是针对多个线程并发访问而设计的,在jdk5.0引入了concurrent包,其中提供了很多并发容器,极大的提升同步容器类的性能。 “分段锁”,JDK8中采用CAS无锁算法 CopyOnWriteArrayList 对应的非并发容器:ArrayList 目标:代替Vector、synchronizedList 原理:利用高并发往往是读多写少的特性 不会阻塞的队列 对应的非并发容器:Queue 原理:基于链表实现的FIFO队列(LinkedList的并发版本) BlockingQueue:数据共享通道 比如,线程A希望线程B发一个消息,用什么方式告知线程
在高并发Java(1):前言中已经提到了无锁的概念,由于在jdk源码中有大量的无锁应用,所以在这里介绍下无锁。 Java当中提供了很多无锁类,下面来介绍下无锁类。 2 无所类的使用 我们已经知道,无锁比阻塞效率要高得多。我们来看看Java是如何实现这些无锁类的。 2.1. 比如String package test; import java.util.concurrent.atomic.AtomicReference; public class Test 1 shift = 31 - Integer.numberOfLeadingZeros(scale); 前导零的意思就是比如8位表示12,00001100,那么前导零就是1前面的0的个数,就是4。 package test; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater
Java程序的进程(Java的一个程序运行在系统中)里至少包含主线程和垃圾回收线程(后台线程)。 [1] main——main线程,用户程序入口 [2] Reference Handler——清除Reference的线程 [3] Finalizer——调用对象finalize方法的线程 [4] 看下面的顺序: 1| 5秒读取文件A 2| 5秒读取文件B + 2秒处理文件A 3| 2秒处理文件B 4| --------------------- 5| 总共需要12秒 CPU等待第一个文件被读取完 ② 系统创建进程时需要为该进程重新分配系统资源,创建线程则代价小很多,因此实现多任务并发时,多线程效率更高. ③ Java语言本身内置多线程功能的支持,而不是单纯第作为底层系统的调度方式,从而简化了多线程编程 courseId=1003108028 《Java零基础入门教程》 《Java并发编程的艺术》 《Java 7并发编程实战手册》
0. 四种状态的锁 锁有四种状态:无锁状态,偏向锁状态,轻量级锁状态,重量级锁状态 根据竞争情况升级 锁可以升级不能降级 1. 偏向锁 大多数情况下,锁不存在多线程竞争,且总是由同一线程多次获得 线程访问同步块并获取锁,就在对象头和栈帧中的锁记录里存储偏向锁ID,之后线程出入同步块就不需要CAS来加锁和解锁,只是测试对象头的Mark Word里是否存在指向该线程的偏向锁。测试成功,线程获得锁,失败,就测试Mark Word中锁标识是否是1(当前锁是偏向锁):没有设置,用CAS竞争锁;设置了,用CAS将对象头
转载:http://www.cnblogs.com/dolphin0520/p/3932921.html 一. java中的ThreadPoolExecutor类 java.util.concurrent.ThreadPoolExecutor 类时线程池中最核心的一个类,因此如果要透彻的了解java中线程池,必须先了解这个类。 ;然后就将任务也分配给这4个临时工人做;如果说这14个工人做任务的速度还是不够,此时工厂主管可能就要考虑不再接收新的任务或者抛弃前面的一些任务了。 这个例子中的corePoolSize就是10,而maximumPoolSize就是14(10+4)。 不过在java doc中,并不提倡我们直接使用ThreadPoolExecutor,而是使用Executors类中提供的几个静态方法来创建线程池: Executors.newCachedThreadPool
所以使用起来相对会有些不便,而Java在这方面提供了相应的同步容器,我们可以在多线程情况下可以结合实际场景考虑使用这些同步容器。 答案是有的,那就是并发容器,有了并发容器后同步容器的使用也越来越少的,大部分都会优先使用并发容器。 本小节将简单介绍一下并发容器,并发容器也称为J.U.C,即是其包名:java.util.concurrent。 ---- 4.HashMap对应的ConcurrentHashMap HashMap的并发安全版本是ConcurrentHashMap,但ConcurrentHashMap不允许 null 值。 的4倍左右。
Java 并发 线程状态转换 新建(New) 创建后尚未启动。 可运行(Runnable) 可能正在运行,也可能正在等待 CPU 时间片。 時雨:在 《Java 并发核心知识体系精讲》中,参考 Oracle 官方文档,标注实现多线程方式只有两种:实现 Runnable 接口和继承 Thread 类。 4 5 5 6 6 7 7 8 8 9 9 2. 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 4. 在 Java 内存模型中,允许编译器和处理器对指令进行重排序,重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。
上篇文章 并发编程3:线程池的使用与执行流程 中我们了解到,线程池中需要使用阻塞队列来保存待执行的任务。这篇文章我们来详细了解下 Java 中的阻塞队列究竟是什么。 七种阻塞队列的前三种 Java 中提供了 7 种 BlockingQueue 的实现,在看线程池之前我根本搞不清楚究竟选择哪个,直到完整地对比总结以后,发现其实也没什么复杂。 notFull; //... } 可以看到,ArrayBlockingQueue 使用可重入锁 ReentrantLock 实现的访问公平性,两个 Condition 保证了添加和获取元素的并发控制 ,这样在添加、获取时通过判断数组元素个数可以感知到并发的获取/添加操作 ;此外就是链表比数组的优势了。 不了解 Comparator 和 Comparable 可以看这篇 Java 解惑:Comparable 和 Comparator 的区别。
reportInterruptAfterWait(interruptMode); } //返回剩余时间 return nanosTimeout - (System.nanoTime() - lastTime); } 4. //2.将头结点的后继结点引用置空 first.nextWaiter = null; //3.将头结点转移到同步队列, 转移完成后有可能唤醒线程 //4.
本文转载自并发编程网,侵删 本文是微信公众号【Java技术江湖】的《Java并发指南》其中一篇,本文大部分内容来源于网络,为了把本文主题讲得清晰透彻,也整合了很多我认为不错的技术博客内容,引用其中了一些比较好的博客文章 该系列博文会告诉你如何全面深入地学习Java并发技术,从Java多线程基础,再到并发编程的基础知识,从Java并发包的入门和实战,再到JUC的源码剖析,一步步地学习Java并发编程,并上手进行实战,以便让你更完整地了解整个 Java并发编程知识体系,形成自己的知识框架。 Java中的锁机制及Lock类 锁的释放-获取建立的happens before 关系 锁是java并发编程中最重要的同步机制。 参考资料 周志明:《深入理解Java虚拟机》 方腾飞:《Java并发编程的艺术》 Java中synchronized的实现原理与应用
Java并发 - (并发基础) 1、什么是共享资源 堆是被所有线程共享的一块内存区域。在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例 Java中几乎所有的对象实例都在这里分配内存。 参考地址:https://zhuanlan.zhihu.com/p/298448987 3、JMM 并发编程的关键目标 并发编程需要处理两个关键问题,即线程之间如何通信和同步。 并发编程的内存模型 共有两种并发编程模型:共享内存模型、消息传递模型,Java采用的是前者。 其中,前4条规则与程序员密切相关。 volatile域的写, happens-before于任意后续对这个volatile域的读; 3、synchronized规则:对一个锁的解锁, happens-before于随后对这个锁的加锁; 4、
4 显示锁和AQS 4.1 Lock接口 核心方法 Java在java.util.concurrent.locks包中提供了一系列的显示锁类,其中最基础的就是Lock接口,该接口提供了几个常见的锁相关的操作 4. 公平锁 ReentrantLock内部利用AQS的线程队列,可以实现公平锁,但是性能相比非公平锁会差一点。 4.不管是ReadLock还是WriteLock都支持Interrupt,语义与ReentrantLock一致。 它是构建锁或者其他同步组件的基础框架(如ReentrantLock、ReentrantReadWriteLock、Semaphore等),是JUC并发包中的核心基础组件。 JUC并发包的作者(Doug Lea)期望它能够成为实现大部分同步需求的基础。 AQS解决了实现同步器时涉及到的大量细节问题,例如获取同步状态、FIFO同步队列。
1.Java容器 1.1.同步容器 Vector ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问。 public V put(K key, V value) { 2 3 return putVal(hash(key), key, value, false, true); 4 这个机制允许任意数量的读线程可以并发访问Map,读者和写者也可以并发访问Map,并且有限数量的写进程还可以并发修改Map,结果是为并发访问带来更高的吞吐量,同时几乎没有损失单个线程访问的性能。 并发队列 2.1.ConcurrentLinkedQueue ConcurrentLinkedQueue:是一个适用于高并发场景下的队列,通过无所的方式,实现了高并发状态下的高性能,通常ConcurrentLinkedQueue 在Java中,BlockingQueue的接口位于java.util.concurrent 包中(在Java5版本开始提供),由上面介绍的阻塞队列的特性可知,阻塞队列是线程安全的。
线程池的返回值ExecutorService简介: ExecutorService是Java提供的用于管理线程池的类。该类的两个作用:控制线程数量和重用线程 2. 具体的4种常用的线程池实现如下:(返回值都是ExecutorService) 2.1 Executors.newCacheThreadPool():可缓存线程池,先查看池中有没有以前建立的线程,如果有, 1正在被执行,打印的值是:1 pool-1-thread-1正在被执行,打印的值是:2 pool-1-thread-1正在被执行,打印的值是:3 pool-1-thread-1正在被执行,打印的值是:4 在保证并发安全的同时,提高了队列的存取效率。 2.
在Java中使用线程封闭技术有:Swing 和 JDBC 的 Connection 对象。 虽然在 Java 语言规范和 Java 内存模型中都没有给出不可变性的正式定义,但不可变性并不等于将对象中的所有域都声明为 final 类型,即使对象中所有的域都是 final 类型的,这个对象也仍然可能是可变的 在 Java 内存模型中,final 域能确保初始化过程的安全性,从而可以不受限制地访问不可变对象,并在共享这些对象时无须同步。 3.6 安全地共享对象在并发程序中使用和共享对象时,可以使用如下一些实用的方法:线程封闭。 线程封闭的对象只能由一个线程拥有,对象被封闭在该线程中,并且只能由这个线程修改。只读共享。 在没有额外同步的情况下,共享的只读对象可以由多个线程并发访问,但任何线程都不能修改它。共享的只读对象包括不可变对象和事实不可变对象。线程安全共享。
线程池的返回值ExecutorService简介: ExecutorService是Java提供的用于管理线程池的类。该类的两个作用:控制线程数量和重用线程 2. 具体的4种常用的线程池实现如下:(返回值都是ExecutorService) 2.1 Executors.newCacheThreadPool():可缓存线程池,先查看池中有没有以前建立的线程,如果有, 主要分享分布式架构、高可扩展、高性能、高并发、性能优化、Spring boot、Redis、ActiveMQ、Nginx、Mycat、Netty、Jvm大型分布式项目实战学习架构师视频。 1正在被执行,打印的值是:1 pool-1-thread-1正在被执行,打印的值是:2 pool-1-thread-1正在被执行,打印的值是:3 pool-1-thread-1正在被执行,打印的值是:4 在保证并发安全的同时,提高了队列的存取效率。 2.
5 并发容器 5.1 Hashtable、HashMap、TreeMap、HashSet、LinkedHashMap 在介绍并发容器之前,先分析下普通的容器,以及相应的实现,方便后续的对比。 1、K key 2、V value 3、Entry<K, V> next 4、int hash 5、Entry<K, V> before 6、Entry<K, V> after 1-4是从HashMap.Entry 1: // Transfer method in java.util.HashMap - 2: // called to resize the hashmap 3: 4: for (int j concurrencyLevel 并发度:默认16。 在高并发下的情况下如何保证取得的元素是最新的?
本篇内容包括:Java 并发工具类的介绍、使用方式与 Demo,包括了 CountDownLatch(线程计数器)、CyclicBarrier(回环栅栏)、Semaphore(信号量) 以及 Exchanger CountDownLatch(线程计数器) CountDownLatch 线程计数器,俗称闭锁,作用是类似加强版的 Join,是让一组线程等待其他的线程完成工作以后才执行 CountDownLatch 类位于 java.util.concurrent 比如有一个任务 A,它要等待其他 4 个任务执行完毕之后才能执行,此时就可以利用 CountDownLatch 来实现这种功能了。 Demo(一组内 4 个线程,每个线程都等待组内所有线程到达 barrier 后,再继续执行): public static void main(String[] args) { int n = 4; CyclicBarrier barrier = new CyclicBarrier(n); for (int i = 0; i < n; i++)
在 Jdk1.5 开始 Java 开始引进提供了 java.util.concurrent.atomic 包,到 Jdk8 时,atomic 包共提供了 16 个原子类,分为 6 种类型,分别是:①、基本类型原子类 当多线程更新变量的值时,可能得不到预期的值,当然增加 syncronized 关键字可以解决线程并发的问题。但原子类提供了一种用法简单,性能高效,线程安全的更新变量的方式。 原子类相较于 synchronized 关键字和 lock,有着以下的优点: 简单:操作简单,底层实现简单 高效:占用资源少,操作速度快 安全:在高并发和多线程环境下要保证数据的正确性 4、Atomic\FieldUpdater(原子更新属性) Atomic\FieldUpdater 原子更新属性,包括三种:AtomicIntegerFieldUpdater、AtomicLongFieldUpdater 但是,在并发量很大的场景下,Atomic 基本类型原子类(AtomicInteger 和 AtomicLong)有很大的性能问题。
大家好,这里是淇妙小屋,一个分享技术,分享生活的博主 后续会发布更多MySQL,Redis,并发,JVM,分布式等面试热点知识,以及Java学习路线,面试重点,职业规划,面经等相关博客 转载请标明出处 Java线程面试题 0.1 线程占用的内存 JDK1.4默认单个线程占用256K JDK1.5默认单个线程占用1M 可以通过-Xss参数设定 0.2 为什么要使用线程池 手动创建线程池的缺点 不受风险控制 消亡的开销,性能佳 线程池优点 降低系统资源消耗,通过重用已存在的线程,降低线程创建和销毁造成的消耗 提高系统响应速度,当有任务到达时,通过复用已存在的线程,无需等待新线程的创建便能立即执行 方便线程并发数的管控 isInterrupted();//返回标识符,并设为false 如果线程抛出InterruptedException,那么在抛出InterruptedException之前,JVM会先将标识符设为false,然后再抛出 4. 实现Callable接口 4. FutureTask(可以由调用线程执行其run(),也可以作为任务提交给线程池) 5. 定时器 6. Stream的parallelStream 7. 线程池隐性创建