package Demo01;
public class Test1 {
public static void main( String[] args ) {
//获取CPU的核数
//CPU密集型,IO密集型
System.out.println(Runtime.getRuntime().availableProcessors());
}
}
public enum State {
//新生
NEW,
//运行
RUNNABLE,
//阻塞
BLOCKED,
//等待,死死的等
WAITING,
//超时等待
TIMED_WAITING,
//终止
TERMINATED;
}
package Demo01;
//基本的买票例子
/*
真正的多线程开发,降低耦合性
线程就是单独的资源类,没有任何附属的操作
1. 属性、方法
*/
public class SaleTicketDemo01 {
public static void main( String[] args ) {
//并发:多线程操作同一个资源类
Ticket ticket = new Ticket();
//函数式接口
new Thread(()->{
for (int i = 0; i < 50; i++) {
ticket.sale();
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 50; i++) {
ticket.sale();
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 50; i++) {
ticket.sale();
}
},"C").start();
}
}
//资源类 oop
class Ticket{
//属性、方法
private int number = 50;
//买票的方式
//synchronized 本质:队列,锁
public synchronized void sale(){
if(number>0){
System.out.println(Thread.currentThread().getName()+"卖出了"+(number--)+"票,剩余:"+number);
}
}
}
package Demo01;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//基本的买票例子
/*
真正的多线程开发,降低耦合性
线程就是单独的资源类,没有任何附属的操作
1. 属性、方法
*/
public class SaleTicketDemo02 {
public static void main( String[] args ) {
//并发:多线程操作同一个资源类
Ticket2 ticket = new Ticket2();
//函数式接口
new Thread(()->{
for (int i = 0; i < 50; i++) ticket.sale(); },"A").start();
new Thread(()->{
for (int i = 0; i < 50; i++) ticket.sale(); },"B").start();
new Thread(()->{ for (int i = 0; i < 50; i++) ticket.sale();},"C").start();
}
}
/*
Lock 三部曲
1. new ReentrantLock
2. Lock.lock();//加锁
3. Lock.unlock();//解锁
*/
//资源类 oop
class Ticket2{
//属性、方法
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();
}
}
}
(死锁)
package Demo01;
/*
线程之间的通信问题:生产者和消费者问题!等待唤醒,通知唤醒
线程交替执行 A B 操作同一个变量 num = 0
A num+1
B nm+1
*/
public class A {
public static void main( String[] args ) {
Data data = new Data();
new Thread(()->{
for (int i = 0; i < 100; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 100; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"B").start();
}
}
//资源类
//等待,业务,通知
class Data{
private int number = 0;
//+1
public synchronized void increment() throws InterruptedException {
if(number!=0){
//等待
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName() + "-----" + number);
///通知其它线程,我+1完毕了
this.notifyAll();
}
//-1
public synchronized void decrement() throws InterruptedException {
if(number==0){
//等待
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName() + "-----" + number);
//通知其它线程,我-1完毕了
this.notifyAll();
}
}
package Demo01;
/*
线程之间的通信问题:生产者和消费者问题!等待唤醒,通知唤醒
线程交替执行 A B 操作同一个变量 num = 0
A num+1
B nm+1
*/
public class A {
public static void main( String[] args ) {
Data data = new Data();
new Thread(()->{
for (int i = 0; i < 100; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 100; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 100; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"C").start();
new Thread(()->{
for (int i = 0; i < 100; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"D").start();
}
}
//资源类
//等待,业务,通知
class Data{
private int number = 0;
//+1
public synchronized void increment() throws InterruptedException {
while(number!=0){
//等待
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName() + "-----" + number);
///通知其它线程,我+1完毕了
this.notifyAll();
}
//-1
public synchronized void decrement() throws InterruptedException {
while(number==0){
//等待
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName() + "-----" + number);
//通知其它线程,我-1完毕了
this.notifyAll();
}
}
package Demo01;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/*
线程之间的通信问题:生产者和消费者问题!等待唤醒,通知唤醒
线程交替执行 A B 操作同一个变量 num = 0
A num+1
B nm+1
*/
public class B {
public static void main( String[] args ) {
Data data = new Data();
new Thread(()->{
for (int i = 0; i < 100; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 100; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 100; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"C").start();
new Thread(()->{
for (int i = 0; i < 100; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"D").start();
}
}
//资源类
//等待,业务,通知
class Data2 {
private int number = 0;
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
// condition.await();//等待
// condition.signalAll();//唤醒全部
//+1
public void increment( ) throws InterruptedException {
lock.lock();
try {
while (number != 0) {
//等待
condition.await();
}
number++;
System.out.println(Thread.currentThread().getName() + "-----" + number);
///通知其它线程,我+1完毕了
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
//-1
public synchronized void decrement () throws InterruptedException {
lock.lock();
try {
while (number == 0) {
//等待
condition.await();
}
number--;
System.out.println(Thread.currentThread().getName() + "-----" + number);
//通知其它线程,我-1完毕了
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
package Demo01;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/*
A执行完调用B
B执行完调用C
C执行完调用A
*/
public class C {
public static void main( String[] args ) {
Data3 data = new Data3();
new Thread(()->{
for (int i = 0; i < 10; i++) {
data.printA();
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
data.printB();
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
data.printC();
}
},"C").start();
}
}
class Data3{//资源类 Lock
private Lock lock =new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();
private int num = 1; //1==A 2==B 3==C
public void printA(){
//业务:判断——》执行——》通知
lock.lock();
try {
while (num!=1){
//等待
condition1.await();
}
System.out.println(Thread.currentThread().getName() + "——>AAAAAAAAAAAAA");
//唤醒:唤醒指定的线程 B
num = 2;
condition2.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printB(){
lock.lock();
//业务:判断——》执行——》通知
try {
while(num!=2){
//等待
condition2.await();
}
//执行
System.out.println(Thread.currentThread().getName() + "——》BBBBBBBBBBBBB");
//唤醒:指定的线程 C
num = 3;
condition3.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printC(){
lock.lock();
//业务:判断——》执行——》通知
try {
while (num!=3){
//等待
condition3.await();
}
//执行
System.out.println(Thread.currentThread().getName() + "——》CCCCCCCCCCCCCCCCCC");
//唤醒指定的线程
num = 1;
condition1.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
package Demo01;
import java.util.concurrent.TimeUnit;
/*
八锁:就是关于锁的八个问题
1.标准情况下,两个线程是先打印发短信还是打电话? 1.发短信 2.打电话
2.sendSms延迟4秒,两个线程先打印 发短信还是打电话? 1.发短信 2.打电话
*/
public class Test01 {
public static void main( String[] args ) {
Phone phone = new Phone();
//锁的存在
new Thread(()->{
phone.sendSms();
},"A").start();
//捕获
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.call();
},"B").start();
}
}
class Phone{
// Synchronized 锁的对象是方法的调用者!
// 两个方法用的是同一个锁,谁先拿到谁执行
public synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
}
package Demo01;
import java.util.concurrent.TimeUnit;
/*
八锁:就是关于锁的八个问题
1.标准情况下,两个线程是先打印发短信还是打电话? 1.发短信 2.打电话
2.sendSms延迟4秒,两个线程先打印 发短信还是打电话? 1.发短信 2.打电话
3.增加了一个普通方法发短信还是hello? 1.hello 2.发短信
4.两个对象,两个同步方法,发短信还是打电话? 1.打电话 2.发短信
*/
public class Test02 {
public static void main( String[] args ) {
//两个对象,两个调用者,两把锁
Phone2 phone = new Phone2();
Phone2 phone2 = new Phone2();
//锁的存在
new Thread(()->{
phone.sendSms();
},"A").start();
//捕获
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
}
}
class Phone2{
// Synchronized 锁的对象是方法的调用者!
// 两个方法用的是同一个锁,谁先拿到谁执行
public synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
//这里没有锁!不是同步方法,不受锁的影响
public void hello(){
System.out.println("hello");
}
}
package Demo01;
import java.util.concurrent.TimeUnit;
/*
八锁:就是关于锁的八个问题
1.标准情况下,两个线程是先打印发短信还是打电话? 1.发短信 2.打电话
2.sendSms延迟4秒,两个线程先打印 发短信还是打电话? 1.发短信 2.打电话
1.标准情况下,两个线程是先打印发短信还是打电话? 1.发短信 2.打电话
2.sendSms延迟4秒,两个线程先打印 发短信还是打电话? 1.发短信 2.打电话
3.增加了一个普通方法发短信还是hello? 1.hello 2.发短信
4.两个对象,两个同步方法,发短信还是打电话? 1.打电话 2.发短信
5.增加两个静态的同步方法,只有一个对象,发短信还是打电话? 1.发短信 2.打电话
6.两个对象!增加两个静态的同步方法,只有一个对象,发短信还是打电话? 1.发短信 2.打电话
*/
public class Test03 {
public static void main( String[] args ) {
//两个对象的Class类模板只有一个;static,锁的是Class
Phone3 phone = new Phone3();
Phone3 phone2 = new Phone3();
//锁的存在
new Thread(()->{
phone.sendSms();
},"A").start();
//捕获
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
}
}
//Phone3唯一的一个Class对象
class Phone3{
// Synchronized 锁的对象是方法的调用者!
// 两个方法用的是同一个锁,谁先拿到谁执行
//static 静态方法;类一加载就有了!Class模板
public static synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public static synchronized void call(){
System.out.println("打电话");
}
}
package Demo01;
import java.util.concurrent.TimeUnit;
/*
八锁:就是关于锁的八个问题
1.标准情况下,两个线程是先打印发短信还是打电话? 1.发短信 2.打电话
2.sendSms延迟4秒,两个线程先打印 发短信还是打电话? 1.发短信 2.打电话
1.标准情况下,两个线程是先打印发短信还是打电话? 1.发短信 2.打电话
2.sendSms延迟4秒,两个线程先打印 发短信还是打电话? 1.发短信 2.打电话
3.增加了一个普通方法发短信还是hello? 1.hello 2.发短信
4.两个对象,两个同步方法,发短信还是打电话? 1.打电话 2.发短信
5.增加两个静态的同步方法,只有一个对象,发短信还是打电话? 1.发短信 2.打电话
6.两个对象!增加两个静态的同步方法,只有一个对象,发短信还是打电话? 1.发短信 2.打电话
7.一个静态同步方法,一个普通同步方法,一个对象,先打印 发短信还是打电话?
8.一个静态同步方法,一个普通同步方法,两个个对象,先打印 发短信还是打电话?
*/
public class Test04 {
public static void main( String[] args ) {
Phone4 phone = new Phone4();
Phone4 phone2 = new Phone4();
//锁的存在
new Thread(()->{
phone.sendSms();
},"A").start();
//捕获
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
}
}
class Phone4{
// 静态同步方法,锁的是Class类模板
public static synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
//普通的同步方法
public synchronized void call(){
System.out.println("打电话");
}
}
package unsafe;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
//java.lang.UnsupportedOperationException 并发修改异常!
public class ListTest {
public static void main( String[] args ) {
/*
并发下Arra不安全的
解决方案:
1. List list = new Vector<>();
2.List list = Collections.synchronizedList(new ArrayList<>());
3.List list = new CopyOnWriteArrayList<>();
*/
// List list = new ArrayList();
// List list = new Vector<>();
// List list = Collections.synchronizedList(new ArrayList<>());
//CopyOnWrite 写入时复制 cow 计算机程序设计领域的一种优化策略;
//多个线程调用的时候,list,读取的时候,固定的,写入(覆盖)
//写入的时候避免覆盖,造成数据问题
//读写分离
//CopyOnWrite
List list = new CopyOnWriteArrayList<>();
for (int i = 1; i < 11; i++) {
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(0,5));
System.out.println(list);
},String.valueOf(i)).start();
}
}
}
package unsafe;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArraySet;
/*
同理可证:java.util.ConcurrentModificationException
1.Set set = Collections.synchronizedSet(new HashSet<>());
2.Set set = new CopyOnWriteArraySet<>();
*/
public class SetTest {
public static void main( String[] args ) {
// Set set = new HashSet<>();
Set<String> set = new CopyOnWriteArraySet<>();
for (int i = 0; i < 30; i++) {
new Thread(()->{
set.add(UUID.randomUUID().toString().substring(0,5));
System.out.println(set);
},String.valueOf(i)).start();
}
}
}
public HashSet() {
map = new HashMap<>();
}
//ass set本质就是map 可以是无法重复的
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
private static final Object PRESENT = new Object();//不变的值
package unsafe;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
//java.util.ConcurrentModificationException
public class MapTest {
public static void main( String[] args ) {
//map是这样用的吗? 不是,大公司不用HashMap
//默认等价于什么? new HashMap<>(16,0.75);
//Map map = new HashMap<>();
Map<String, String> map = new ConcurrentHashMap<>();
for (int i = 0; i < 30; i++) {
new Thread(()->{
map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0,5));
System.out.println(map);
},String.valueOf(i)).start();
}
}
}
支持检索的完全并发性和更新的高预期并发性的哈希表。 这个类服从相同功能规范如Hashtable ,并且包括对应于每个方法的方法版本Hashtable 。 不过,尽管所有操作都是线程安全的,检索操作并不意味着锁定,并没有为防止所有访问的方式锁定整个表的任何支持。 这个类可以在依赖于线程安全性的程序中与Hashtable完全互Hashtable ,但不依赖于其同步细节。
检索操作(包括get )通常不阻止,因此可能与更新操作重叠(包括put和remove )。 检索反映了最近完成的更新操作的结果。 (更正式地,对于给定密钥的更新操作熊之前发生与任何(非空关系)检索该键报告经更新的值。)对于聚合操作,比如putAll和clear ,并发检索可能反映插入或移除只有一些条目。 类似地,迭代器,分割器和枚举返回在反映迭代器/枚举创建过程中或之后反映哈希表状态的元素。 他们不抛出ConcurrentModificationException 。 然而,迭代器被设计为一次只能由一个线程使用。 请记住,骨料状态方法的结果,包括size , isEmpty和containsValue通常是有用的,只有当一个地图没有发生在其他线程并发更新。 否则,这些方法的结果反映了可能足以用于监视或估计目的的瞬态状态,但不适用于程序控制。
当存在太多的冲突(即,具有不同的哈希码但是以表的大小为模数落入相同的时隙的密钥)时,该表被动态扩展,并且每个映射保持大致两个bin的预期平均效果(对应于0.75负载因素阈值调整大小)。 由于映射被添加和删除,这个平均值可能会有很大差异,但是总的来说,这为哈希表保留了普遍接受的时间/空间权衡。 然而,调整这个或任何其他类型的散列表可能是相对较慢的操作。 如果可能,最好提供一个尺寸估计作为可选的initialCapacity构造函数参数。 附加的可选的loadFactor构造函数参数提供了另外的手段,通过指定在计算给定数量的元素时要分配的空间量时使用的表密度来定制初始表容量。 此外,为了与此类的先前版本兼容,构造函数可以可选地指定预期的concurrencyLevel作为内部大小调整的附加提示。 请注意,使用完全相同的许多键hashCode()是降低任何哈希表的hashCode()的一种可靠的方法。 为了改善影响,当按键为Comparable时,该类可以使用键之间的比较顺序来帮助打破关系。
甲Set投影一个的ConcurrentHashMap可以(使用被创建newKeySet()或newKeySet(int) ),或观察(使用keySet(Object)时仅键是感兴趣的,并且被映射的值是(可能瞬时)不使用或全部取相同的映射值。
ConcurrentHashMap可以通过使用LongAdder值并通过computeIfAbsent进行初始化,将其用作可缩放的频率映射(直方图或多集的形式)。 例如,要向ConcurrentHashMap
此类及其视图和迭代器实现所有的可选方法Map个Iterator接口。
像Hashtable但不像HashMap ,这个类不允许 null用作键或值。
ConcurrentHashMaps支持一组顺序和并行批量操作,与大多数Stream方法不同,它们被设计为安全并且经常明智地应用,即使是由其他线程同时更新的映射; 例如,当计算共享注册表中的值的快照摘要时。 有三种操作,每种具有四种形式,接受键,值,条目和(键,值)参数和/或返回值的函数。 由于ConcurrentHashMap的元素不以任何特定的方式排序,并且可能会在不同的并行执行中以不同的顺序进行处理,因此提供的函数的正确性不应取决于任何排序,也不应依赖于可能瞬时变化的任何其他对象或值计算进行中; 除了每一个行动,理想情况下都是无副作用的。 对Map.Entry对象的批量操作不支持方法setValue 。
批量操作的并发属性遵循ConcurrentHashMap的并发属性:从get(key)返回的任何非空结果和相关的访问方法与相关的插入或更新都有一个发生之前的关系。 任何批量操作的结果都反映了这些每个元素关系的组成(但是除非以某种方式已知是静态的,它们并不一定是相对于整个地图的原子)。 相反,因为映射中的键和值从不为空,所以null作为目前缺乏任何结果的可靠原子指标。 为了保持此属性,null用作所有非标量缩减操作的隐含基础。 对于double,long和int版本,基础应该是当与任何其他值组合时返回其他值(更正式地,它应该是减少的标识元素)。 大多数常见的减少具有这些属性; 例如,使用基数0或最小值与基准MAX_VALUE计算和。
作为参数提供的搜索和转换函数应该类似地返回null以指示缺少任何结果(在这种情况下不被使用)。 在映射缩减的情况下,这也使得转换可以用作过滤器,如果不应该组合元素,返回null(或者在原始专业化的情况下,身份基础)。 在使用它们进行搜索或减少操作之前,您可以通过在“null意味着现在没有任何内容”规则下自行构建复合转换和过滤。
接受和/或返回Entry参数的方法维护键值关联。 例如,当找到最大价值的钥匙时,它们可能是有用的。 请注意,可以使用new AbstractMap.SimpleEntry(k,v)提供“plain”Entry new AbstractMap.SimpleEntry(k,v) 。
批量操作可能突然完成,抛出在应用程序中遇到的异常。 在处理这样的异常时,请注意,其他并发执行的函数也可能引发异常,或者如果没有发生第一个异常,则会这样做。
与顺序形式相比,加速比是常见的,但不能保证。 如果并行计算的基础工作比计算本身更昂贵,则涉及小地图上的简短功能的并行操作可能比顺序形式执行得更慢。 类似地,如果所有处理器正忙于执行不相关的任务,并行化可能不会导致太多的实际并行。
所有任务方法的所有参数都必须为非空值。
这个班是Java Collections Framework的会员 。
package callable;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class CallableTest {
public static void main( String[] args ) {
// new Thread(new MyThread()).start();
// new Thread(new FutureTask()).start();
// new Thread(new FutureTask(Callable)).start();
new Thread().start();//怎么启动callable
MyThread thread = new MyThread();
//适配类
FutureTask<Integer> futureTask = new FutureTask<>(thread);
new Thread(futureTask,"A").start();
new Thread(futureTask,"B").start(); //此时线程不是NEW状态,第一次调用时返回结果保存了
try {
Integer integer = futureTask.get(); //获取callable返回结果 (方法可能会产生阻塞!把他放到最后或者通过异步通信来处理)
System.out.println(integer);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
class MyThread implements Callable<Integer> {
@Override
public Integer call( ) {
System.out.println("call()");
//耗时的操作
return 1024;
}
}
package Demo01;
import java.util.concurrent.CountDownLatch;
//计数器
public class CountDownLatchDemo {
public static void main( String[] args ) throws InterruptedException {
//总数是6
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 1; i < 7; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName() + "Go out");
countDownLatch.countDown();//数量-1
},String.valueOf(i)).start();
}
countDownLatch.await(); //等待计数器归零,然后再向下执行
System.out.println("Close Door");
}
}
package Demo01;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierDemo {
public static void main( String[] args ) {
//集齐七颗龙珠召唤神龙
//召唤龙珠的线程
CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{
System.out.println("召唤神龙成功");
});
for (int i = 1; i < 8; 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();
}
}
}
package Demo01;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class SemaphoreDemo {
public static void main( String[] args ) {
//线程数量:停车位; 限流
Semaphore semaphore = new Semaphore(3);
for (int i = 1; i < 7; i++) {
new Thread(()->{
//acquire() 得到
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{
//release() 释放
semaphore.release();
}
},String.valueOf(i)).start();
}
}
}
package Demo01;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/*
独占锁(写锁) 一次只能被一个线程占有
共享锁(读锁) 多个线程可以同时占有
读——读 //可以共存
读——写 //不能共存
写——写 //不能共存
*/
public class ReadWriteLockDemo {
public static void main( String[] args ) {
MyCacheLock myCache = new MyCacheLock();
//写入
for (int i = 1; i < 6; i++) {
final int temp =i;
new Thread(()->{
myCache.put(temp+"",temp+"");
},String.valueOf(i)).start();
}
//读取
for (int i = 1; i < 6; i++) {
final int temp =i;
new Thread(()->{
myCache.get(temp+"");
},String.valueOf(i)).start();
}
}
}
//加锁
class MyCacheLock{
private volatile Map<String,Object> map = new HashMap<>();
//读写锁:更加细粒度的控制
private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
//存,写入的时候,只希望同时只有一个线程写
public void put(String key,Object value){
readWriteLock.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 {
readWriteLock.writeLock().unlock();
}
}
//取,读;所有人都可以读
public void get(String key){
readWriteLock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "读取" + key);
Object o = map.get(key);
System.out.println(Thread.currentThread().getName() + "读取完毕") ;
} catch (Exception e) {
e.printStackTrace();
} finally {
readWriteLock.readLock().unlock();
}
}
}
/*
自定义缓存
*/
class MyCache{
private volatile Map<String,Object> map = new HashMap<>();
//存,写
public void put(String key,Object value){
System.out.println(Thread.currentThread().getName() + "写入" + key);
map.put(key,value);
System.out.println(Thread.currentThread().getName() + "写入完毕") ;
}
//取,读
public void get(String key){
System.out.println(Thread.currentThread().getName() + "读取" + key);
Object o = map.get(key);
System.out.println(Thread.currentThread().getName() + "读取完毕") ;
}
}
package bq;
import java.util.concurrent.ArrayBlockingQueue;
public class Test {
public static void main( String[] args ) {
test1();
}
/*
抛出异常
*/
public static void test1(){
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
System.out.println(blockingQueue.add("A"));
System.out.println(blockingQueue.add("B"));
System.out.println(blockingQueue.add("C"));
//java.lang.IllegalStateException: Queue full 抛出异常!
//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());
//java.util.NoSuchElementException 抛出异常!
System.out.println(blockingQueue.remove());
}
}
package bq;
import java.util.concurrent.ArrayBlockingQueue;
public class Test {
public static void main( String[] args ) {
test2();
}
/*
抛出异常
*/
public static void test1(){
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
System.out.println(blockingQueue.add("A"));
System.out.println(blockingQueue.add("B"));
System.out.println(blockingQueue.add("C"));
//java.lang.IllegalStateException: Queue full 抛出异常!
//System.out.println(blockingQueue.add("D"));
System.out.println("=======================");
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
//java.util.NoSuchElementException 抛出异常!
System.out.println(blockingQueue.remove());
}
/*
有返回值没有异常
*/
public static void test2(){
//队列大小
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
System.out.println(blockingQueue.offer("A"));
System.out.println(blockingQueue.offer("B"));
System.out.println(blockingQueue.offer("C"));
//System.out.println(blockingQueue.offer("D"));//false 不抛出异常!
System.out.println(blockingQueue.peek()); //检查队首元素
System.out.println("=======================");
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());//null 不抛出异常
}
}
package bq;
import java.util.concurrent.ArrayBlockingQueue;
public class Test {
public static void main( String[] args ) throws InterruptedException {
test3();
}
/*
抛出异常
*/
public static void test1(){
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
System.out.println(blockingQueue.add("A"));
System.out.println(blockingQueue.add("B"));
System.out.println(blockingQueue.add("C"));
//java.lang.IllegalStateException: Queue full 抛出异常!
//System.out.println(blockingQueue.add("D"));
System.out.println("=======================");
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
//java.util.NoSuchElementException 抛出异常!
System.out.println(blockingQueue.remove());
}
/*
有返回值没有异常
*/
public static void test2(){
//队列大小
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
System.out.println(blockingQueue.offer("A"));
System.out.println(blockingQueue.offer("B"));
System.out.println(blockingQueue.offer("C"));
//System.out.println(blockingQueue.offer("D"));//false 不抛出异常!
System.out.println(blockingQueue.peek()); //检查队首元素
System.out.println("=======================");
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());//null 不抛出异常
}
/*
等待,阻塞(一直等待)
*/
public static void test3() throws InterruptedException {
//队列大小
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
blockingQueue.put("A");
blockingQueue.put("B");
blockingQueue.put("C");
//blockingQueue.put("D");//队列没有位置了,一直阻塞
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());//没有这个元素,一直阻塞
}
}
package bq;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
public class Test {
public static void main( String[] args ) throws InterruptedException {
test4();
}
/*
抛出异常
*/
public static void test1(){
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
System.out.println(blockingQueue.add("A"));
System.out.println(blockingQueue.add("B"));
System.out.println(blockingQueue.add("C"));
//java.lang.IllegalStateException: Queue full 抛出异常!
//System.out.println(blockingQueue.add("D"));
System.out.println("=======================");
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
//java.util.NoSuchElementException 抛出异常!
System.out.println(blockingQueue.remove());
}
/*
有返回值没有异常
*/
public static void test2(){
//队列大小
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
System.out.println(blockingQueue.offer("A"));
System.out.println(blockingQueue.offer("B"));
System.out.println(blockingQueue.offer("C"));
//System.out.println(blockingQueue.offer("D"));//false 不抛出异常!
System.out.println(blockingQueue.peek()); //检查队首元素
System.out.println("=======================");
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());//null 不抛出异常
}
/*
等待,阻塞(一直等待)
*/
public static void test3() throws InterruptedException {
//队列大小
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
blockingQueue.put("A");
blockingQueue.put("B");
blockingQueue.put("C");
//blockingQueue.put("D");//队列没有位置了,一直阻塞
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());//没有这个元素,一直阻塞
}
/*
超时等待
*/
public static void test4() throws InterruptedException {
//队列大小
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
System.out.println(blockingQueue.offer("A"));
System.out.println(blockingQueue.offer("B"));
System.out.println(blockingQueue.offer("C"));
System.out.println(blockingQueue.offer("D",2, TimeUnit.SECONDS));//等待超过两秒就退出
System.out.println("=======================");
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll(2,TimeUnit.SECONDS));
}
}
package bq;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
//同步队列
/*
和其他BlockingQueue不一样,SynchronousQueue不存储元素
put了一个元素,必须从里面先take取出来,否则不能在put进去值
*/
public class SynchronizedQueueDemo {
public static void main( String[] args ) {
SynchronousQueue<String > synchronousQueue = new SynchronousQueue<>(); //同步队列
new Thread(()->{
try {
System.out.println(Thread.currentThread().getName() + "put 1");
synchronousQueue.put("1");
System.out.println(Thread.currentThread().getName() + "put 2");
synchronousQueue.put("2");
System.out.println(Thread.currentThread().getName() + "put 3");
synchronousQueue.put("3");
} catch (InterruptedException e) {
e.printStackTrace();
}
},"T1").start();
new Thread(()->{
try {
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + "->"+synchronousQueue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + "->"+synchronousQueue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + "->"+synchronousQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
},"T2").start();
}
}
线程可以复用、可以控制最大并发数、管理线程
package pool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
//Executors 工具类、三大方法
//使用了线程池之后,使用线程池来创建线程
public class Demo01 {
public static void main( String[] args ) {
//ExecutorService threadPool = Executors.newSingleThreadExecutor();//单个线程处理
//ExecutorService threadPool = Executors.newFixedThreadPool(5); //创建一个固定的线程池大小
ExecutorService threadPool = Executors.newCachedThreadPool(); //可伸缩,遇强则强,遇弱则弱
try {
for (int i = 0; i < 100; i++) {
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName() + " OK");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//线程池用完,程序结束,关闭线程池
threadPool.shutdown();
}
}
}
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE, //21亿
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
public ThreadPoolExecutor(int corePoolSize, //核心线程池大小
int maximumPoolSize, //最大核心线程大小
long keepAliveTime, //空闲线程存活时间
TimeUnit unit, //超时单位
BlockingQueue<Runnable> workQueue, //阻塞队列
ThreadFactory threadFactory, //线程工厂,创建线程的,一般不用动
RejectedExecutionHandler handler //拒绝策略
) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
package pool;
import java.util.concurrent.*;
//Executors 工具类、三大方法
//使用了线程池之后,使用线程池来创建线程
public class Demo01 {
public static void main( String[] args ) {
//自定义线程池!
ExecutorService threadPool = new ThreadPoolExecutor(2,
5,
3,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()); //阻塞队列满了,还有人进来,不处理这个人的,抛出异常
try {
//最大承载:Qeque+max
//超过 java.util.concurrent.RejectedExecutionException:
for (int i = 0; i < 9; i++) {
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName() + " OK");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//线程池用完,程序结束,关闭线程池
threadPool.shutdown();
}
}
}
package function;
import java.util.function.Function;
/*
Function 函数型接口,有一个输入参数,有一个输出
只要是函数型接口就可以用lambda表达式简化
*/
public class Demo01 {
public static void main( String[] args ) {
//工具类:输入输入的值
// Function function = new Function() {
// @Override
// public String apply( String str ) {
// return str;
// }
// };
Function<String ,String > function= (str)->{return str;};
System.out.println(function.apply("123"));
}
}
package function;
import java.util.function.Predicate;
/*
断定型接口:有一个参数,返回值只能是 布尔值!
*/
public class Demo02 {
public static void main( String[] args ) {
//判断字符串是否为空
Predicate<String > predicate = (s)->{
return s.isEmpty();
};
System.out.println(predicate.test("123"));
}
}
package function;
import java.util.function.Consumer;
/*
Consumer 消费型接口:只有输入,没有返回值
*/
public class Demo03 {
public static void main( String[] args ) {
Consumer<String > consumer = (str)->{
System.out.println(str);
};
consumer.accept("Java学不会");
}
}
package function;
import java.util.function.Supplier;
/*
Supplier 供给型接口 没有参数,只有返回值
*/
public class Demo04 {
public static void main( String[] args ) {
Supplier<Integer> supplier = ()->{return 1024;};
System.out.println(supplier.get());
}
}
什么是Stream流式计算
大数据:存储+计算
存储:集合、MySQL等
计算:都是交个流来操作,流不存储,相当于数据库的查询
实例:
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class Stream_Demo {
public static void main(String[] args) {
User u1 = new User("a",20,1);
User u2 = new User("b",21,2);
User u3 = new User("c",22,3);
User u4 = new User("Sky",23,4);
User u5 = new User("Song",24,5);
List<User> userList = Arrays.asList(u1,u2,u3,u4,u5);
userList.stream()
//过滤年龄大于22岁的人
.filter((user)->{return user.getAge() > 22;})
//返回大写的名字
.map((user)->{return user.getName().toUpperCase();})
.sorted(Comparator.reverseOrder())//倒序
.forEach(System.out::println);//打印
}
}
ForkJoin特点:工作窃取(大数据量时使用)
测试类
package forkjoin;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;
public class Test {
public static void main( String[] args ) throws ExecutionException, InterruptedException {
// test1(); //389
// test2(); //257
// test3(); //210
}
//普通的
public static void test1(){
long start = System.currentTimeMillis();
//分支合并
long sum = 0;
for (long i = 1; i <= 10_0000_0000; i++) {
sum+=i;
}
long end = System.currentTimeMillis();
System.out.println("sum="+sum+"时间:"+(end-start));
}
//forkjoin
public static void test2() throws ExecutionException, InterruptedException {
long start = System.currentTimeMillis();
ForkJoinPool forkJoinPool = new ForkJoinPool();
ForkJoinTask<Long> task = new Demo01(1, 10_0000_0000);
ForkJoinTask<Long> submit = forkJoinPool.submit(task); //提交任务
Long sum = submit.get();
long end = System.currentTimeMillis();
System.out.println("sum="+sum+"时间:"+(end-start));
}
//Stream并行流()
public static void test3(){
long start = System.currentTimeMillis();
long sum = LongStream.rangeClosed(1, 10_0000_0000).parallel().reduce(0, Long::sum);
long end = System.currentTimeMillis();
System.out.println("sum="+sum+"时间:"+(end-start));
}
}
测试:
package forkjoin;
import java.util.concurrent.RecursiveTask;
/*
求和计算
如何使用forkjoin
1.forkjoinpool通过它来执行
2.计算任务
3.计算类要继承ForkJoin
*/
public class Demo01 extends RecursiveTask<Long> {
private long start; //1
private long end; //2_0000_0000
//临界值
private Long temp = 100000L;
public Demo01( long start, long end ) {
this.start = start;
this.end = end;
}
//计算方法
@Override
protected Long compute( ) {
if((end-start)<temp){
//分支合并
long sum = 0;
for (long i = start; i <= end; i++) {
sum+=i;
}
return sum;
}else { //forkjoin
long middle = (start+end)/2; //中间值
Demo01 demo01 = new Demo01(start, middle);
demo01.fork(); //拆分任务,把任务亚茹线程队列
Demo01 demo02 = new Demo01(middle+1, end);
demo02.fork(); //拆分任务,把任务亚茹线程队列
return demo01.join() + demo02.join();
}
}
}
package future;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
/*
异步调用:CompletableFuture
1.异步执行
2.成功回调
3.失败回调
*/
public class Demo01 {
public static void main( String[] args ) throws ExecutionException, InterruptedException {
// //没有返回值的异步回调 runAsync
// CompletableFuture completableFuture = CompletableFuture.runAsync(()->{
// try {
// TimeUnit.SECONDS.sleep(2);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// System.out.println(Thread.currentThread().getName() + "runAsync=》Void");
// });
//
// System.out.println("Java学不会");
// completableFuture.get(); //获取执行结果
//有返回值的异步回调 supplyAsync
CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(()->{
System.out.println(Thread.currentThread().getName()+"completableFuture");
int i=10/0;
return 1024;
});
System.out.println(completableFuture.whenComplete(( t, u ) -> {
System.out.println("t=>" + t); //正常的返回结果
System.out.println("u=>" + u); //错误信息:
}).exceptionally(( e ) -> {
e.getMessage();
return 233;
}).get());
}
}
立刻
刷回主存。package tvolatile;
import java.util.concurrent.TimeUnit;
public class JMMDemo {
private static int num =0;
public static void main( String[] args ) {//main
new Thread(()->{ //线程1
while(num==0){
}
}).start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
num=1;
System.out.println(num);
}
}
Volatile是Java虚拟机提供轻量级的同步机制
1. 保证可见性
2.不保证原子性
3. 静止命令重排
package tvolatile;
import java.util.concurrent.TimeUnit;
public class JMMDemo {
//不加Volatile程序就会死循环
//加玻璃他提了可以保证可见性
private volatile static int num =0;
public static void main( String[] args ) {//main
new Thread(()->{ //线程1 //对主内存的变化不知道
while(num==0){
}
}).start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
num=1;
System.out.println(num);
}
}
package tvolatile;
//不保证原子性
public class VDome01 {
//volatile不保证原子性
private volatile static int num = 0;
public static void add(){
num++;
}
public static void main( String[] args ) {
for (int i = 1; i < 21; i++) {
new Thread(()->{
for (int i1 = 0; i1 < 1000; i1++) {
add();
}
}).start();
}
while (Thread.activeCount()>2){ //main gc
Thread.yield();
}
System.out.println(Thread.currentThread().getName() + " " + num);
}
}
使用原子类
)package tvolatile;
import java.util.concurrent.atomic.AtomicInteger;
//不保证原子性
public class VDome01 {
//volatile不保证原子性
private volatile static AtomicInteger num = new AtomicInteger();
public static void add(){
num.getAndIncrement(); //AtomicInteger+1 方法 CAS
}
public static void main( String[] args ) {
for (int i = 1; i < 21; i++) {
new Thread(()->{
for (int i1 = 0; i1 < 1000; i1++) {
add();
}
}).start();
}
while (Thread.activeCount()>2){ //main gc
Thread.yield();
}
System.out.println(Thread.currentThread().getName() + " " + num);
}
}
什么是指令重排:你写的程序,计算机并不是按照你写的那样去执行
源代码——>编译器优化的重排——>指令并行也可能会重排——>内存系统也会重排——>执行
处理器在进行指令重排的时候,考虑数据直接的依赖性
package single;
//饿汉式单例
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];
private Hungry(){
}
private final static Hungry HUNGRY = new Hungry();
public static Hungry getInstance(){
return HUNGRY;
}
}
package single;
import com.sun.xml.internal.ws.runtime.config.TubelineFeatureReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
//懒汉式单例
//道高一尺魔高一丈
public class LazyMan {
private static boolean flag = false;
private LazyMan(){
synchronized (LazyMan.class){
if(flag==false){
flag= true;
}else {
throw new RuntimeException("不要视图通过反射破坏异常");
}
}
System.out.println(Thread.currentThread().getName() + " ok");
}
public volatile static LazyMan lazyMan;
//双重检测锁模式的 懒汉单例模式 DCL懒汉锁
public static LazyMan getInstance(){
if(lazyMan==null){
synchronized (LazyMan.class){
if(lazyMan==null){
lazyMan = new LazyMan(); //不防止指令重排,需要加volatile
/*
1.分配内存
2.执行构造方法,初始化对象
3.把这个对象指向这个空间
123
132 A
B //此时lazyMan还没有完成构造
*/
}
}
}
return lazyMan;
}
//反射
public static void main( String[] args ) throws Exception {
// LazyMan instance = LazyMan.getInstance();
Field flag = LazyMan.class.getDeclaredField("flag");
flag.setAccessible(true);
Constructor<LazyMan> declaredConstructor = LazyMan.class.getDeclaredConstructor(null);
declaredConstructor.setAccessible(true);
LazyMan instance = declaredConstructor.newInstance();
flag.set(instance,false);
LazyMan instance2 = declaredConstructor.newInstance();
System.out.println(instance);
System.out.println(instance2);
}
}
package single;
//静态内部类
public class Holder {
private Holder(){
}
public static Holder getInstance(){
return InnerClass.HOLDER;
}
public static class InnerClass{
private static final Holder HOLDER = new Holder();
}
}
package single;
import java.lang.reflect.Constructor;
//enum 是一个什么? 本身也是一个Class类
public enum EnumSingle {
INSTANCE;
public EnumSingle getInstance(){
return INSTANCE;
}
}
class Tesst{
public static void main( String[] args ) throws NoSuchMethodException {
EnumSingle instance1 = EnumSingle.INSTANCE;
EnumSingle instance2 = EnumSingle.INSTANCE;
Constructor<EnumSingle> declaredConstructor = EnumSingle.class.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
System.out.println(instance1);
System.out.println(instance2);
}
}
什么是CAS
package cas;
import java.util.concurrent.atomic.AtomicInteger;
public class CASDemo {
//CAS compareAndSet : 比较并交换!
public static void main( String[] args ) {
AtomicInteger atomicInteger = new AtomicInteger(2022);
//期望、更新
//public final boolean compareAndSet(int expect, int update)
//如果期望的值达到了,那么就更新,否则不更新 CAS 是CPU的并发原因
System.out.println(atomicInteger.compareAndSet(2022, 2023));
System.out.println(atomicInteger.get());
System.out.println(atomicInteger.compareAndSet(2022, 2024));
System.out.println(atomicInteger.get());
}
}
package cas;
import java.util.concurrent.atomic.AtomicInteger;
public class CASDemo {
//CAS compareAndSet : 比较并交换!
public static void main( String[] args ) {
AtomicInteger atomicInteger = new AtomicInteger(2022);
//期望、更新
//public final boolean compareAndSet(int expect, int update)
//如果期望的值达到了,那么就更新,否则不更新 CAS 是CPU的并发原因
//===========捣乱的线程===========
System.out.println(atomicInteger.compareAndSet(2022, 2018));
System.out.println(atomicInteger.get());
System.out.println(atomicInteger.compareAndSet(2018, 2022));
System.out.println(atomicInteger.get());
//===========期望的线程===========
System.out.println(atomicInteger.compareAndSet(2022, 2020));
System.out.println(atomicInteger.get());
}
}
解决ABA问题,引入原子引用!对应的思想:乐观锁
package cas;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;
public class CASDemo {
//CAS compareAndSet : 比较并交换!
public static void main( String[] args ) {
// AtomicInteger atomicInteger = new AtomicInteger(2022);
//AtomicStampedReference 注意:如果泛型是一个包装类,注意对象的引用问题
AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100,1);
new Thread(()->{
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
int stamp = atomicStampedReference.getStamp();//获得版本号
System.out.println("a1=>" + stamp);
System.out.println(atomicStampedReference.compareAndSet(100, 101,
atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1));
System.out.println("a2=>" + atomicStampedReference.getStamp());
System.out.println(atomicStampedReference.compareAndSet(101, 100,
atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1));
System.out.println("a3=>" + atomicStampedReference.getStamp());
},"a").start();
new Thread(()->{
System.out.println("===============");
int stamp = atomicStampedReference.getStamp();//获得版本号
System.out.println("b1=>" + stamp);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(atomicStampedReference.compareAndSet(100, 106,
atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1));
System.out.println("b2=>" + atomicStampedReference.getStamp());
System.out.println(atomicStampedReference.getReference());
},"b").start();
}
}
package lock;
import java.util.concurrent.TimeUnit;
//Synchronized
public class Demo01 {
public static void main( String[] args ) {
Phone phone = new Phone();
new Thread(()->{
phone.sms();
},"A").start();
new Thread(()->{
phone.sms();
},"B").start();
}
}
class Phone{
public synchronized void sms(){
System.out.println(Thread.currentThread().getName() + " sms");
call(); //这里也有锁
}
public synchronized void call(){
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " call");
}
}
package lock;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Demo02 {
public static void main( String[] args ) {
Phone2 phone = new Phone2();
new Thread(()->{
phone.sms();
},"A").start();
new Thread(()->{
phone.sms();
},"B").start();
}
}
class Phone2{
Lock lock = new ReentrantLock();
public void sms(){
lock.lock(); //Lock锁必须配对,否则会死锁
try {
System.out.println(Thread.currentThread().getName() + " sms");
call(); //这里也有锁
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void call(){
lock.lock();
try {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " call");
} finally {
lock.unlock();
}
}
}
package lock;
import java.util.concurrent.atomic.AtomicReference;
/*
自旋锁
*/
public class SpinlockDemo {
AtomicReference<Thread> atomicReference = new AtomicReference<>();
//加锁
public void myLock(){
Thread thread = Thread.currentThread();
//自旋锁
while (!atomicReference.compareAndSet(null, thread)) {
}
System.out.println(thread.getName()+"=======>myLock");
}
//减锁
public void myUnLock(){
Thread thread = Thread.currentThread();
atomicReference.compareAndSet(thread, null);
System.out.println(thread.getName() + "======>myUnLock");
}
}
package lock;
import java.util.concurrent.TimeUnit;
public class TestSpinLock {
public static void main( String[] args ) {
//底层使用的自旋锁CAS
SpinlockDemo lock = new SpinlockDemo();
new Thread(()->{
lock.myLock();
try {
TimeUnit.SECONDS.sleep(3);
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.myUnLock();
}
},"T1").start();
new Thread(()->{
lock.myLock();
try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.myUnLock();
}
},"T2").start();
}
}
如何排查死锁
当我们出现死锁的时候,首先需要使用jps -l命令查看运行的程序
我们能看到DeadLockDemo这个类,一直在运行
在使用jstack查看堆栈信息
通过查看最后一行,我们看到 Found 1 deadlock,即存在一个死锁