diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..454757c Binary files /dev/null and b/.DS_Store differ diff --git a/README.md b/README.md index 4d66a32..79d2603 100755 --- a/README.md +++ b/README.md @@ -1,66 +1,22 @@ ## 1 目标 -致力于建立全球最完善的 Java 高并发理论体系。让我们的程序更加可靠,跳槽面试更轻松。 +致力于构建全球最完善的 Java 高并发理论体系。让我们的程序更加可靠,跳槽面试更轻松。 -## 2 深入底层原理,实现并发业务 -- 线程N种实现方式 - -- 线程启动你真的会么? - -- 线程停止、中断的最佳实践 - -- 线程生命周期 - -- 趣解Thread和Object类中线程相关方法:wait、notify、join、yield… - -- 线程属性 - -- 线程异常处理 - -- 线程安全与程序性能的取舍之道 - -... - -## 3 环境参数 - -- Maven 3.6+ - -- JDK 8+ - -- Tomcat 8.5+ - -- MySQL 8.0.16+ - -- Redis 6.0+ - -- Intellij IDEA 2019.3 - -## 4 方案概要 +## 高并发方案概要 ### 线程安全性 -线程安全性,主要从原子性、可见性、有序性三个方面 - -原子性部分, atomic包下相关类、CAS原理、Unsafe类、synchronized关键字等的使用及注意事项 - -可见性部分,主要介绍的是volatile关键字的规则和使用,及synchronized关键字的可见性 - -有序性部分,则重点讲解了happens-before原则 +线程安全性,主要从原子性、可见性、有序性 ### 安全发布对象 -安全发布对象的一些核心方法,主要通过单例类的多种实现方式,让大家在实现过程中去体会这些方法的具体含义 -这也是对线程安全性的巩固,也是把线程安全性涉及的一些关键字和类再一次放到实际场景中使用,加深大家对他们的印象和认识 +安全发布对象的一些核心方法,主要通过单例类的多种实现方式体会,这也是对线程安全性的巩固,也是把线程安全性涉及的一些关键字和类再一次放到实际场景使用。 ### 线程安全策略 线程安全策略,包括定义不可变对象、线程封闭、同步容器、并发容器等,引出并发里的关键知识J.U.C。 - -同时还额外介绍了开发中常见的一些线程不安全类和写法,并给出他们各自对应的替代方案。这一章涉及的内容在日常开发和面试中都会涉及很多。... +同时还额外介绍了开发中常见的一些线程不安全类和写法,并给出他们各自对应的替代方案。 ### AQS +J.U.C的重要组件,面试必问考点。 -J.U.C的重要组件,也是面试的重要考点。 - -AQS模型设计及相关同步组件的原理和使用,都非常实用 - -具体包括:CountDownLatch、Semaphore、CyclicBarrier、ReentrantLock与锁、Condition等。 +AQS模型设计及相关同步组件的原理和使用,都非常实用,包括:CountDownLatch、Semaphore、CyclicBarrier、ReentrantLock与锁、Condition等。 这些组件需要大家能熟练明白他们的用途及差异,不但会使用,而且还要明确知道不同方法调用后的不同效果。 @@ -71,38 +27,52 @@ J.U.C相关组件,主要包括FutureTask、Fork/Join框架、BlockingQueue, 这些组件使用场景相对AQS会少一些,但也是J.U.C的重要组成部分,也是需要掌握的 ### 线程调度-线程池 -J.U.C里最后一部分:线程池。面试大概率会问到线程池相关的知识点。 +new Thread弊端、线程池的好处、ThreadPoolExecutor详细介绍(参数、状态、方法)、线程池类图、Executor框架接口 -这一章将主要从new Thread弊端、线程池的好处、ThreadPoolExecutor详细介绍(参数、状态、方法)、线程池类图、Executor框架接口等进行讲解,需要大家能了解线程池的许多细节及配置,并能在实际项目中正确使用 - -### 多线程并发拓展讲解 -对并发编程做些补充,但都贴近当前的面试,主要讲解死锁产生的条件及预防、多线程并发编程的最佳实践、Spring与线程安全、以及面试都特别喜欢问的HashMap和ConcurrentMap源码细节。当然,面试喜欢问的问题,对实际项目开发也是特别重要的 +### 多线程并发拓展 +死锁产生的条件及预防、多线程并发编程的最佳实践、Spring与线程安全、以及面试都特别喜欢问的HashMap和ConcurrentMap源码细节 ### 扩容 -高并发部分:思路,侧重面试,扩容思路,首先介绍垂直扩容和水平扩容的区别,数据库读操作扩展和写操作扩展思路。 +垂直扩容和水平扩容的区别,数据库读操作扩展和写操作扩展 ### 缓存 -思路,本章讲解高并发中缓存方案。 - -包含对缓存特征(命中率、最大元素、清空策略)、影响缓存命中率因素、缓存分类和应用场景(本地缓存、分布式缓存)、高并发场景下缓存常见问题(缓存一致性、缓存并发、缓存穿透、雪崩)等的具体介绍。此外,针对大家常用的缓存组件Guava Cache、Memcache、Redis +缓存特征(命中率、最大元素、清空策略)、影响缓存命中率因素、缓存分类和应用场景(本地缓存、分布式缓存)、高并发场景下缓存常见问题(缓存一致性、缓存并发、缓存穿透、雪崩) -### 消息队列 -消息队列的特性(业务无关、FIFO、容灾、性能)、为什么需要消息队列以及消息队列的好处(业务解耦、最终一致性、广播、错峰与流控),对当前比较流行的消息队列组件kafka和rabbitmq做架构分析和特性介绍 +### MQ +消息队列的特性(业务无关、FIFO、容灾、性能)、为什么需要消息队列以及消息队列的好处(业务解耦、最终一致性、广播、错峰与流控) -### 应用拆分 -从实际项目拆分步骤讲起,让大家可以实际感受到应用拆分的好处和解决的问题,之后引出对应用拆分原则(业务优先、循序渐进、兼顾技术、可靠测试)和应用拆分时思考的内容(应用之间通信、应用之间数据库设计、避免事务跨应用),并引出对服务化Dubbo和微服务Spring Cloud的框架介绍 +### 应用拆分 ### 限流 明确限流的重要作用 -限流常用的四种算法:计数法、滑动窗口、漏桶算法和令牌桶算法,并对他们做了简单的对比 +限流常用的四种算法:计数法、滑动窗口、漏桶算法和令牌桶算法 ### 服务降级与服务熔断 服务降级的分类:自动降级(超时、失败次数、故障、限流)和人工降级(开关),总结了服务降级和服务熔断的共性(目的、最终表现、粒度、自治)和区别(出发原因、管理目标层次、实现方式)以及服务降级要考虑的问题 -### 数据库分库分表与高可用 -高并发部分:主讲思路,从数据库瓶颈开始讲起,引出对数据库切库分库分表的介绍。数据库切库里重点介绍了读写分离的设计,对比支持多数据源和分库的区别; +### 分库分表 + +## QQ 技术交流群 + +为大家提供一个学习交流平台,在这里你可以自由地讨论技术问题。 + + + +## 微信交流群 + + +### 本人微信 + + +## Java源码模拟面试解析指南 + + + + -什么时候该考虑分表、横向分表与纵向分表,以及通过mybatis的分页插件shardbatis2.0实现数据库分表 +### 绘图工具 +- [draw.io](https://www.draw.io/) +- keynote ## 知识体系 ![](https://uploadfiles.nowcoder.com/files/20190815/5088755_1565799768221_4685968-76a236d781f7dee7.png) diff --git a/assets/LOGO.png b/assets/LOGO.png new file mode 100644 index 0000000..b5e3b09 Binary files /dev/null and b/assets/LOGO.png differ diff --git "a/assets/QQ \347\276\244.JPG" "b/assets/QQ \347\276\244.JPG" new file mode 100644 index 0000000..c6a3f39 Binary files /dev/null and "b/assets/QQ \347\276\244.JPG" differ diff --git "a/assets/\344\270\252\344\272\272\345\276\256\344\277\241.jpeg" "b/assets/\344\270\252\344\272\272\345\276\256\344\277\241.jpeg" new file mode 100644 index 0000000..35b73f0 Binary files /dev/null and "b/assets/\344\270\252\344\272\272\345\276\256\344\277\241.jpeg" differ diff --git "a/assets/\345\205\254\344\274\227\345\217\267.png" "b/assets/\345\205\254\344\274\227\345\217\267.png" new file mode 100644 index 0000000..e8c9c92 Binary files /dev/null and "b/assets/\345\205\254\344\274\227\345\217\267.png" differ diff --git "a/assets/\345\276\256\344\277\241\347\276\244.jpeg" "b/assets/\345\276\256\344\277\241\347\276\244.jpeg" new file mode 100644 index 0000000..abeb9ae Binary files /dev/null and "b/assets/\345\276\256\344\277\241\347\276\244.jpeg" differ diff --git "a/assets/\347\211\233\345\256\242\344\270\223\345\210\212.png" "b/assets/\347\211\233\345\256\242\344\270\223\345\210\212.png" new file mode 100644 index 0000000..6f48493 Binary files /dev/null and "b/assets/\347\211\233\345\256\242\344\270\223\345\210\212.png" differ diff --git a/mvnw b/mvnw index 5bf251c..df68171 100755 --- a/mvnw +++ b/mvnw @@ -55,7 +55,7 @@ case "`uname`" in MINGW*) mingw=true;; Darwin*) darwin=true # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + # See https://developer.JavaEdge.com/library/mac/qa/qa1170/_index.html if [ -z "$JAVA_HOME" ]; then if [ -x "/usr/libexec/java_home" ]; then export JAVA_HOME="`/usr/libexec/java_home`" diff --git a/pom.xml b/pom.xml index 9eade25..19c29f6 100755 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,6 @@ com.javaedge concurrency 0.0.1-SNAPSHOT - war concurrency Demo project for Spring Boot @@ -90,6 +89,20 @@ compile + + org.projectlombok + lombok + + + junit + junit + + + + io.netty + netty-all + 4.1.15.Final + diff --git a/src/main/java/AppendixA/Main.java b/src/main/java/AppendixA/Main.java new file mode 100644 index 0000000..ebfb1b9 --- /dev/null +++ b/src/main/java/AppendixA/Main.java @@ -0,0 +1,9 @@ +package main.java.AppendixA; + +public class Main { + public static void main(String[] args) { + System.out.println(Thread.currentThread().getName() + ":BEGIN"); + new MyFrame(); + System.out.println(Thread.currentThread().getName() + ":END"); + } +} diff --git a/src/main/java/AppendixA/MyFrame.java b/src/main/java/AppendixA/MyFrame.java new file mode 100644 index 0000000..7e8fa87 --- /dev/null +++ b/src/main/java/AppendixA/MyFrame.java @@ -0,0 +1,63 @@ +package main.java.AppendixA; + +import javax.swing.JFrame; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.SwingUtilities; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + + +public class MyFrame extends JFrame implements ActionListener { + private final JLabel label = new JLabel("Event Dispatching Thread Sample"); + private final JButton button = new JButton("countUp"); + public MyFrame() { + super("MyFrame"); + getContentPane().setLayout(new FlowLayout()); + getContentPane().add(label); + getContentPane().add(button); + button.addActionListener(this); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + pack(); + setVisible(true); + } + public void actionPerformed(ActionEvent e) { + if (e.getSource() == button) { + countUp(); + } + } + private void countUp() { + System.out.println(Thread.currentThread().getName() + ":countUp:BEGIN"); + + // invokerThread��ָ��ʱ����sleep֮�󣬵���SwingUtilities.invokeLater + new Thread("invokerThread") { + public void run() { + System.out.println(Thread.currentThread().getName() + ":invokerThread:BEGIN"); + for (int i = 0; i < 10; i++) { + final String string = "" + i; + try { + // executor�ᱻ��Event Dispatching Thread���� + final Runnable executor = new Runnable() { + public void run() { + System.out.println(Thread.currentThread().getName() + ":executor:BEGIN:string = " + string); + label.setText(string); + System.out.println(Thread.currentThread().getName() + ":executor:END"); + } + }; + + // ��Event Dispatching Thread���ó�exector + SwingUtilities.invokeLater(executor); + + Thread.sleep(1000); + } catch (Exception e) { + e.printStackTrace(); + } + } + System.out.println(Thread.currentThread().getName() + ":invokerThread:END"); + } + }.start(); + + System.out.println(Thread.currentThread().getName() + ":countUp:END"); + } +} diff --git a/src/main/java/Balking/Q5/TestThread.java b/src/main/java/Balking/Q5/TestThread.java new file mode 100644 index 0000000..2c4466f --- /dev/null +++ b/src/main/java/Balking/Q5/TestThread.java @@ -0,0 +1,15 @@ +package main.java.Balking.Q5; + +public class TestThread extends Thread { + public void run() { + System.out.print("BEGIN"); + for (int i = 0; i < 50; i++) { + System.out.print("."); + try { + Thread.sleep(100); + } catch (InterruptedException e) { + } + } + System.out.println("END"); + } +} diff --git a/src/main/java/Balking/Sample/ChangerThread.java b/src/main/java/Balking/Sample/ChangerThread.java new file mode 100644 index 0000000..e058762 --- /dev/null +++ b/src/main/java/Balking/Sample/ChangerThread.java @@ -0,0 +1,26 @@ +//package Balking.Sample; +// +//import java.io.IOException; +//import java.util.Random; +// +//public class ChangerThread extends Thread { +// private Data data; +// private Random random = new Random(); +// public ChangerThread(String name, Data data) { +// super(name); +// this.data = data; +// } +// public void run() { +// try { +// for (int i = 0; true; i++) { +// data.change("No." + i); //�޸����Ϯ� +// Thread.sleep(random.nextInt(1000)); // ģ��ȥ��������� +// data.save(); // ��ȷ��Ҫ��浵 +// } +// } catch (IOException e) { +// e.printStackTrace(); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } +// } +//} diff --git a/src/main/java/Immutable/A6_2/Main.java b/src/main/java/Immutable/A6_2/Main.java new file mode 100644 index 0000000..1f8fec5 --- /dev/null +++ b/src/main/java/Immutable/A6_2/Main.java @@ -0,0 +1,31 @@ +//package Immutable.A6_2; +// +//import person.MutablePerson; +//import person.ImmutablePerson; +// +//public class Main { +// public static void main(String[] args) { +// MutablePerson mutable = new MutablePerson("start", "start"); +// new CrackerThread(mutable).start(); +// new CrackerThread(mutable).start(); +// new CrackerThread(mutable).start(); +// for (int i = 0; true; i++) { +// mutable.setPerson("" + i, "" + i); +// } +// } +//} +// +//class CrackerThread extends Thread { +// private final MutablePerson mutable; +// public CrackerThread(MutablePerson mutable) { +// this.mutable = mutable; +// } +// public void run() { +// while (true) { +// ImmutablePerson immutable = new ImmutablePerson(mutable); +// if (!immutable.getName().equals(immutable.getAddress())) { +// System.out.println(currentThread().getName() + " ***** BROKEN ***** " + immutable); +// } +// } +// } +//} diff --git a/src/main/java/Immutable/Q2/Main.java b/src/main/java/Immutable/Q2/Main.java new file mode 100644 index 0000000..8216518 --- /dev/null +++ b/src/main/java/Immutable/Q2/Main.java @@ -0,0 +1,8 @@ +package main.java.Immutable.Q2; + +public class Main { + public static void main(String[] args) { + String s = "BAT"; + System.out.println(s.replace('B', 'C')); // 'B'ȡ����'C' + } +} diff --git a/concurrency/src/main/java/com/javaedge/concurrency/ConcurrencyApplication.java b/src/main/java/com/javaedge/concurrency/ConcurrencyApplication.java similarity index 95% rename from concurrency/src/main/java/com/javaedge/concurrency/ConcurrencyApplication.java rename to src/main/java/com/javaedge/concurrency/ConcurrencyApplication.java index edd52be..aec342b 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/ConcurrencyApplication.java +++ b/src/main/java/com/javaedge/concurrency/ConcurrencyApplication.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency; +package main.java.com.javaedge.concurrency; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/ConcurrencyTest.java b/src/main/java/com/javaedge/concurrency/ConcurrencyTest.java similarity index 96% rename from concurrency/src/main/java/com/javaedge/concurrency/ConcurrencyTest.java rename to src/main/java/com/javaedge/concurrency/ConcurrencyTest.java index 2967863..12867a7 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/ConcurrencyTest.java +++ b/src/main/java/com/javaedge/concurrency/ConcurrencyTest.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency; +package main.java.com.javaedge.concurrency; import com.javaedge.concurrency.annoations.NotThreadSafe; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/HttpFilter.java b/src/main/java/com/javaedge/concurrency/HttpFilter.java similarity index 90% rename from concurrency/src/main/java/com/javaedge/concurrency/HttpFilter.java rename to src/main/java/com/javaedge/concurrency/HttpFilter.java index aec3df4..87dcb65 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/HttpFilter.java +++ b/src/main/java/com/javaedge/concurrency/HttpFilter.java @@ -1,6 +1,6 @@ -package com.javaedge.concurrency; +package main.java.com.javaedge.concurrency; -import com.javaedge.concurrency.example.threadLocal.RequestHolder; +import com.javaedge.concurrency.threadLocal.RequestHolder; import lombok.extern.slf4j.Slf4j; import javax.servlet.Filter; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/HttpInterceptor.java b/src/main/java/com/javaedge/concurrency/HttpInterceptor.java similarity index 87% rename from concurrency/src/main/java/com/javaedge/concurrency/HttpInterceptor.java rename to src/main/java/com/javaedge/concurrency/HttpInterceptor.java index 4ed6d77..5172654 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/HttpInterceptor.java +++ b/src/main/java/com/javaedge/concurrency/HttpInterceptor.java @@ -1,6 +1,6 @@ -package com.javaedge.concurrency; +package main.java.com.javaedge.concurrency; -import com.javaedge.concurrency.example.threadLocal.RequestHolder; +import com.javaedge.concurrency.threadLocal.RequestHolder; import lombok.extern.slf4j.Slf4j; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/LockSupportBlockerTest.java b/src/main/java/com/javaedge/concurrency/LockSupportBlockerTest.java similarity index 88% rename from concurrency/src/main/java/com/javaedge/concurrency/example/LockSupportBlockerTest.java rename to src/main/java/com/javaedge/concurrency/LockSupportBlockerTest.java index a4c018c..7b9ae45 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/LockSupportBlockerTest.java +++ b/src/main/java/com/javaedge/concurrency/LockSupportBlockerTest.java @@ -1,3 +1,8 @@ +package main.java.com.javaedge.concurrency; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.LockSupport; + public class LockSupportBlockerTest { public static void main(String[] args) { Thread t3 = new Thread(() -> { diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/LockSupportTest.java b/src/main/java/com/javaedge/concurrency/LockSupportTest.java similarity index 97% rename from concurrency/src/main/java/com/javaedge/concurrency/example/LockSupportTest.java rename to src/main/java/com/javaedge/concurrency/LockSupportTest.java index 624b1cb..6b3f543 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/LockSupportTest.java +++ b/src/main/java/com/javaedge/concurrency/LockSupportTest.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example; +package main.java.com.javaedge.concurrency; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.LockSupport; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/TestController.java b/src/main/java/com/javaedge/concurrency/TestController.java similarity index 89% rename from concurrency/src/main/java/com/javaedge/concurrency/TestController.java rename to src/main/java/com/javaedge/concurrency/TestController.java index bc49c01..1429afc 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/TestController.java +++ b/src/main/java/com/javaedge/concurrency/TestController.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency; +package main.java.com.javaedge.concurrency; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Controller; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/UnsafeTest.java b/src/main/java/com/javaedge/concurrency/UnsafeTest.java similarity index 72% rename from concurrency/src/main/java/com/javaedge/concurrency/example/UnsafeTest.java rename to src/main/java/com/javaedge/concurrency/UnsafeTest.java index 138606c..6459a0a 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/UnsafeTest.java +++ b/src/main/java/com/javaedge/concurrency/UnsafeTest.java @@ -1,19 +1,26 @@ +package main.java.com.javaedge.concurrency; + +import sun.misc.Unsafe; + +import java.lang.reflect.Field; +import java.util.concurrent.TimeUnit; + +/** + * @author JavaEdge + */ public class UnsafeTest { public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { Field f = Unsafe.class.getDeclaredField("theUnsafe"); f.setAccessible(true); Unsafe unsafe = (Unsafe) f.get(null); - Thread t1 = new Thread() { - @Override - public void run() { - Thread.currentThread().setName("t1"); - System.out.println(Thread.currentThread().getName() + " before park"); - //park 100 seconds - unsafe.park(false, TimeUnit.NANOSECONDS.convert(100, TimeUnit.SECONDS)); - System.out.println(Thread.currentThread().getName() + " after park"); - } - }; + Thread t1 = new Thread(() -> { + Thread.currentThread().setName("t1"); + System.out.println(Thread.currentThread().getName() + " before park"); + //park 100 seconds + unsafe.park(false, TimeUnit.NANOSECONDS.convert(100, TimeUnit.SECONDS)); + System.out.println(Thread.currentThread().getName() + " after park"); + }); Thread t2 = new Thread() { @Override public void run() { diff --git a/concurrency/src/main/java/com/javaedge/concurrency/annoations/NotRecommend.java b/src/main/java/com/javaedge/concurrency/annoations/NotRecommend.java similarity index 86% rename from concurrency/src/main/java/com/javaedge/concurrency/annoations/NotRecommend.java rename to src/main/java/com/javaedge/concurrency/annoations/NotRecommend.java index b1f1268..51563d1 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/annoations/NotRecommend.java +++ b/src/main/java/com/javaedge/concurrency/annoations/NotRecommend.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.annoations; +package main.java.com.javaedge.concurrency.annoations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/annoations/NotThreadSafe.java b/src/main/java/com/javaedge/concurrency/annoations/NotThreadSafe.java similarity index 86% rename from concurrency/src/main/java/com/javaedge/concurrency/annoations/NotThreadSafe.java rename to src/main/java/com/javaedge/concurrency/annoations/NotThreadSafe.java index 3413bd8..479d656 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/annoations/NotThreadSafe.java +++ b/src/main/java/com/javaedge/concurrency/annoations/NotThreadSafe.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.annoations; +package main.java.com.javaedge.concurrency.annoations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/annoations/Recommend.java b/src/main/java/com/javaedge/concurrency/annoations/Recommend.java similarity index 86% rename from concurrency/src/main/java/com/javaedge/concurrency/annoations/Recommend.java rename to src/main/java/com/javaedge/concurrency/annoations/Recommend.java index 6e8c350..ca616cc 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/annoations/Recommend.java +++ b/src/main/java/com/javaedge/concurrency/annoations/Recommend.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.annoations; +package main.java.com.javaedge.concurrency.annoations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/annoations/ThreadSafe.java b/src/main/java/com/javaedge/concurrency/annoations/ThreadSafe.java similarity index 86% rename from concurrency/src/main/java/com/javaedge/concurrency/annoations/ThreadSafe.java rename to src/main/java/com/javaedge/concurrency/annoations/ThreadSafe.java index c38ef6f..e248e53 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/annoations/ThreadSafe.java +++ b/src/main/java/com/javaedge/concurrency/annoations/ThreadSafe.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.annoations; +package main.java.com.javaedge.concurrency.annoations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/CountDownLatchExample1.java b/src/main/java/com/javaedge/concurrency/aqs/CountDownLatchExample1.java similarity index 95% rename from concurrency/src/main/java/com/javaedge/concurrency/example/aqs/CountDownLatchExample1.java rename to src/main/java/com/javaedge/concurrency/aqs/CountDownLatchExample1.java index ce28dda..7cbc186 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/CountDownLatchExample1.java +++ b/src/main/java/com/javaedge/concurrency/aqs/CountDownLatchExample1.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.aqs; +package main.java.com.javaedge.concurrency.aqs; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/CountDownLatchExample2.java b/src/main/java/com/javaedge/concurrency/aqs/CountDownLatchExample2.java similarity index 95% rename from concurrency/src/main/java/com/javaedge/concurrency/example/aqs/CountDownLatchExample2.java rename to src/main/java/com/javaedge/concurrency/aqs/CountDownLatchExample2.java index 65dacf0..2ae325e 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/CountDownLatchExample2.java +++ b/src/main/java/com/javaedge/concurrency/aqs/CountDownLatchExample2.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.aqs; +package main.java.com.javaedge.concurrency.aqs; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/CyclicBarrierExample1.java b/src/main/java/com/javaedge/concurrency/aqs/CyclicBarrierExample1.java similarity index 95% rename from concurrency/src/main/java/com/javaedge/concurrency/example/aqs/CyclicBarrierExample1.java rename to src/main/java/com/javaedge/concurrency/aqs/CyclicBarrierExample1.java index f117926..694afd5 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/CyclicBarrierExample1.java +++ b/src/main/java/com/javaedge/concurrency/aqs/CyclicBarrierExample1.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.aqs; +package main.java.com.javaedge.concurrency.aqs; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/CyclicBarrierExample2.java b/src/main/java/com/javaedge/concurrency/aqs/CyclicBarrierExample2.java similarity index 96% rename from concurrency/src/main/java/com/javaedge/concurrency/example/aqs/CyclicBarrierExample2.java rename to src/main/java/com/javaedge/concurrency/aqs/CyclicBarrierExample2.java index 19024d8..3894267 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/CyclicBarrierExample2.java +++ b/src/main/java/com/javaedge/concurrency/aqs/CyclicBarrierExample2.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.aqs; +package main.java.com.javaedge.concurrency.aqs; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/CyclicBarrierExample3.java b/src/main/java/com/javaedge/concurrency/aqs/CyclicBarrierExample3.java similarity index 95% rename from concurrency/src/main/java/com/javaedge/concurrency/example/aqs/CyclicBarrierExample3.java rename to src/main/java/com/javaedge/concurrency/aqs/CyclicBarrierExample3.java index 90663bc..18f0926 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/CyclicBarrierExample3.java +++ b/src/main/java/com/javaedge/concurrency/aqs/CyclicBarrierExample3.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.aqs; +package main.java.com.javaedge.concurrency.aqs; import lombok.extern.slf4j.Slf4j; diff --git a/src/main/java/com/javaedge/concurrency/aqs/SampleLock.java b/src/main/java/com/javaedge/concurrency/aqs/SampleLock.java new file mode 100644 index 0000000..b2334f1 --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/aqs/SampleLock.java @@ -0,0 +1,25 @@ +package main.java.com.javaedge.concurrency.aqs; + +/** + * @author JavaEdge + * @date 2021/4/21 + */ +class SampleLock { + volatile int state; + + /** + * 加锁 + */ + void lock() { + // ... + state = 1; + } + + /** + * 解锁 + */ + void unlock() { + // ... + state = 0; + } +} diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/SimpleLock.java b/src/main/java/com/javaedge/concurrency/aqs/SimpleLock.java similarity index 92% rename from concurrency/src/main/java/com/javaedge/concurrency/example/aqs/SimpleLock.java rename to src/main/java/com/javaedge/concurrency/aqs/SimpleLock.java index e82953c..86d9fdd 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/SimpleLock.java +++ b/src/main/java/com/javaedge/concurrency/aqs/SimpleLock.java @@ -1,3 +1,8 @@ +package main.java.com.javaedge.concurrency.aqs; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.AbstractQueuedSynchronizer; + public class SimpleLock { private static class Sync extends AbstractQueuedSynchronizer { @Override diff --git a/src/main/java/com/javaedge/concurrency/aqs/semaphore/MicrowaveOvenPool.java b/src/main/java/com/javaedge/concurrency/aqs/semaphore/MicrowaveOvenPool.java new file mode 100644 index 0000000..50ccf81 --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/aqs/semaphore/MicrowaveOvenPool.java @@ -0,0 +1,87 @@ +package main.java.com.javaedge.concurrency.aqs.semaphore; + +import javax.validation.constraints.NotNull; +import java.util.List; +import java.util.Vector; +import java.util.concurrent.Semaphore; +import java.util.function.Function; + +/** + * @author JavaEdge + * @date 2021/4/22 + */ +class Food { + + public String name; + + private long warmTime; + + public Food(String name, long warmTime) { + this.name = name; + this.warmTime = warmTime; + } + + public String getName() { + return name; + } + + public long getWarmTime() { + return warmTime; + } +} + +class MicrowaveOven { + + public String name; + + public MicrowaveOven(String name) { + this.name = name; + } + + public Food warm(Food food) { + long second = food.getWarmTime() * 1000; + try { + Thread.sleep(second); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + System.out.println(String.format("%s warm %s %d seconds food.", name, food.getName(), food.getWarmTime())); + return food; + } + + public String getName() { + return name; + } +} + +/** + * @author JavaEdge + */ +public class MicrowaveOvenPool { + + private List microwaveOvens; + + private Semaphore semaphore; + + public MicrowaveOvenPool(int size, @NotNull List microwaveOvens) { + this.microwaveOvens = new Vector<>(microwaveOvens); + this.semaphore = new Semaphore(size); + } + + public Food exec(Function func) { + MicrowaveOven microwaveOven = null; + try { + semaphore.acquire(); + microwaveOven = microwaveOvens.remove(0); + return func.apply(microwaveOven); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + microwaveOvens.add(microwaveOven); + semaphore.release(); + } + return null; + } + +} diff --git a/src/main/java/com/javaedge/concurrency/aqs/semaphore/ObjPool.java b/src/main/java/com/javaedge/concurrency/aqs/semaphore/ObjPool.java new file mode 100644 index 0000000..d1397cb --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/aqs/semaphore/ObjPool.java @@ -0,0 +1,71 @@ +package main.java.com.javaedge.concurrency.aqs.semaphore; + +import lombok.extern.slf4j.Slf4j; + +import java.util.List; +import java.util.Vector; +import java.util.concurrent.Semaphore; +import java.util.function.Function; + +/** + * @author JavaEdge + * @date 2021/4/22 + */ +@Slf4j +public class ObjPool { + + final List pool; + + /** + * 用信号量实现限流器 + */ + final Semaphore sem; + + ObjPool(int size, T t) { + // 使用线程安全的vector,因为信号量支持多个线程进入临界区 + // 执行 add、remove 方法时可能有并发 + pool = new Vector() {}; + for (int i = 0; i < size; i++) { + pool.add(t); + } + sem = new Semaphore(size); + } + + /** + * 利用对象池的对象,调用func + */ + R exec(Function func) throws InterruptedException { + T t = null; + // 前10个线程调用acquire()方法,都能继续执行,相当于通过了信号灯 + // 而其他线程则会阻塞在acquire() + sem.acquire(); + try { + // 通过信号灯的线程,为每个线程分配一个对象 t + t = pool.remove(0); + // 执行回调方法 + R apply = func.apply(t); + return apply; + } finally { + // 执行完回调后,释放对象 + pool.add(t); + + /** + * 更新信号量的计数器 + * 如果此时信号量里计数器的值≤0,说明有线程在等待 + * 此时会自动唤醒等待的线程 + */ + sem.release(); + } + } + + public static void main(String[] args) throws InterruptedException { + // 创建对象池 + ObjPool pool = new ObjPool<>(10, 2L); + // 通过对象池获取t,之后执行 + pool.exec(t -> { + log.info("t:{}", t); + return t.toString(); + }); + } +} + diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/SemaphoreExample1.java b/src/main/java/com/javaedge/concurrency/aqs/semaphore/SemaphoreExample1.java similarity index 83% rename from concurrency/src/main/java/com/javaedge/concurrency/example/aqs/SemaphoreExample1.java rename to src/main/java/com/javaedge/concurrency/aqs/semaphore/SemaphoreExample1.java index 62c25e2..bcf563b 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/SemaphoreExample1.java +++ b/src/main/java/com/javaedge/concurrency/aqs/semaphore/SemaphoreExample1.java @@ -1,16 +1,18 @@ -package com.javaedge.concurrency.example.aqs; +package main.java.com.javaedge.concurrency.aqs.semaphore; import lombok.extern.slf4j.Slf4j; -import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; +/** + * @author JavaEdge + */ @Slf4j public class SemaphoreExample1 { - private final static int threadCount = 20; + private final static int THREAD_COUNT = 20; public static void main(String[] args) throws Exception { @@ -18,7 +20,7 @@ public static void main(String[] args) throws Exception { final Semaphore semaphore = new Semaphore(3); - for (int i = 0; i < threadCount; i++) { + for (int i = 0; i < THREAD_COUNT; i++) { final int threadNum = i; exec.execute(() -> { try { diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/SemaphoreExample2.java b/src/main/java/com/javaedge/concurrency/aqs/semaphore/SemaphoreExample2.java similarity index 94% rename from concurrency/src/main/java/com/javaedge/concurrency/example/aqs/SemaphoreExample2.java rename to src/main/java/com/javaedge/concurrency/aqs/semaphore/SemaphoreExample2.java index 47ce2b4..b3c55b3 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/SemaphoreExample2.java +++ b/src/main/java/com/javaedge/concurrency/aqs/semaphore/SemaphoreExample2.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.aqs; +package main.java.com.javaedge.concurrency.aqs.semaphore; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/SemaphoreExample3.java b/src/main/java/com/javaedge/concurrency/aqs/semaphore/SemaphoreExample3.java similarity index 92% rename from concurrency/src/main/java/com/javaedge/concurrency/example/aqs/SemaphoreExample3.java rename to src/main/java/com/javaedge/concurrency/aqs/semaphore/SemaphoreExample3.java index 9c0ebb7..f9fe06d 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/SemaphoreExample3.java +++ b/src/main/java/com/javaedge/concurrency/aqs/semaphore/SemaphoreExample3.java @@ -1,11 +1,10 @@ -package com.javaedge.concurrency.example.aqs; +package main.java.com.javaedge.concurrency.aqs.semaphore; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; -import java.util.concurrent.TimeUnit; @Slf4j public class SemaphoreExample3 { diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/SemaphoreExample4.java b/src/main/java/com/javaedge/concurrency/aqs/semaphore/SemaphoreExample4.java similarity index 95% rename from concurrency/src/main/java/com/javaedge/concurrency/example/aqs/SemaphoreExample4.java rename to src/main/java/com/javaedge/concurrency/aqs/semaphore/SemaphoreExample4.java index c73e5af..29a3658 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/SemaphoreExample4.java +++ b/src/main/java/com/javaedge/concurrency/aqs/semaphore/SemaphoreExample4.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.aqs; +package main.java.com.javaedge.concurrency.aqs.semaphore; import lombok.extern.slf4j.Slf4j; diff --git a/src/main/java/com/javaedge/concurrency/aqs/semaphore/SemaphoreExample5.java b/src/main/java/com/javaedge/concurrency/aqs/semaphore/SemaphoreExample5.java new file mode 100755 index 0000000..b462d07 --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/aqs/semaphore/SemaphoreExample5.java @@ -0,0 +1,49 @@ +package main.java.com.javaedge.concurrency.aqs.semaphore; + +import lombok.extern.slf4j.Slf4j; + +import java.util.Queue; + +/** + * @author JavaEdge + */ +@Slf4j +public class SemaphoreExample5 { + /** + * 计数器 + */ + int count; + + /** + * 等待队列 + */ + Queue queue; + + /** + * 初始化 + * + * @param c + */ + void Semaphore(int c){ + this.count=c; + } + + void down(){ + this.count--; + if(this.count<0){ + // 将当前线程插入等待队列 + // 阻塞当前线程 + } + } + void up(){ + this.count++; + if(this.count<=0) { + // 移除等待队列中的某个线程t + // 唤醒线程t + } + } + + public static void main(String[] args) { + + } +} diff --git a/src/main/java/com/javaedge/concurrency/aqs/semaphore/SemaphoreExample6.java b/src/main/java/com/javaedge/concurrency/aqs/semaphore/SemaphoreExample6.java new file mode 100755 index 0000000..ecdd6ba --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/aqs/semaphore/SemaphoreExample6.java @@ -0,0 +1,34 @@ +package main.java.com.javaedge.concurrency.aqs.semaphore; + +import java.util.concurrent.Semaphore; + +/** + * @author JavaEdge + */ +public class SemaphoreExample6 { + + static int count; + + /** + * 初始化信号量 + */ + static final Semaphore SEMAPHORE = new Semaphore(1); + + /** + * 信号量保证互斥 + */ + static void add() throws InterruptedException { + // 进入临界区之前执行 + SEMAPHORE.acquire(); + try { + count += 1; + } finally { + // 退出临界区之前执行 + SEMAPHORE.release(); + } + } + + public static void main(String[] args) throws InterruptedException { + add(); + } +} diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/atomic/AtomicExample1.java b/src/main/java/com/javaedge/concurrency/atomic/AtomicExample1.java similarity index 92% rename from concurrency/src/main/java/com/javaedge/concurrency/example/atomic/AtomicExample1.java rename to src/main/java/com/javaedge/concurrency/atomic/AtomicExample1.java index eaba128..f309866 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/atomic/AtomicExample1.java +++ b/src/main/java/com/javaedge/concurrency/atomic/AtomicExample1.java @@ -1,6 +1,6 @@ -package com.javaedge.concurrency.example.atomic; +package main.java.com.javaedge.concurrency.atomic; -import com.javaedge.concurrency.annoations.ThreadSafe; +import main.java.com.javaedge.concurrency.annoations.ThreadSafe; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.CountDownLatch; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/atomic/AtomicExample2.java b/src/main/java/com/javaedge/concurrency/atomic/AtomicExample2.java similarity index 92% rename from concurrency/src/main/java/com/javaedge/concurrency/example/atomic/AtomicExample2.java rename to src/main/java/com/javaedge/concurrency/atomic/AtomicExample2.java index 452bfb4..42aed35 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/atomic/AtomicExample2.java +++ b/src/main/java/com/javaedge/concurrency/atomic/AtomicExample2.java @@ -1,6 +1,6 @@ -package com.javaedge.concurrency.example.atomic; +package main.java.com.javaedge.concurrency.atomic; -import com.javaedge.concurrency.annoations.ThreadSafe; +import main.java.com.javaedge.concurrency.annoations.ThreadSafe; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.CountDownLatch; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/atomic/AtomicExample3.java b/src/main/java/com/javaedge/concurrency/atomic/AtomicExample3.java similarity index 92% rename from concurrency/src/main/java/com/javaedge/concurrency/example/atomic/AtomicExample3.java rename to src/main/java/com/javaedge/concurrency/atomic/AtomicExample3.java index c6e20d3..ece69ca 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/atomic/AtomicExample3.java +++ b/src/main/java/com/javaedge/concurrency/atomic/AtomicExample3.java @@ -1,6 +1,6 @@ -package com.javaedge.concurrency.example.atomic; +package main.java.com.javaedge.concurrency.atomic; -import com.javaedge.concurrency.annoations.ThreadSafe; +import main.java.com.javaedge.concurrency.annoations.ThreadSafe; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.CountDownLatch; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/atomic/AtomicExample4.java b/src/main/java/com/javaedge/concurrency/atomic/AtomicExample4.java similarity index 81% rename from concurrency/src/main/java/com/javaedge/concurrency/example/atomic/AtomicExample4.java rename to src/main/java/com/javaedge/concurrency/atomic/AtomicExample4.java index d2b3c25..1238f30 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/atomic/AtomicExample4.java +++ b/src/main/java/com/javaedge/concurrency/atomic/AtomicExample4.java @@ -1,6 +1,6 @@ -package com.javaedge.concurrency.example.atomic; +package main.java.com.javaedge.concurrency.atomic; -import com.javaedge.concurrency.annoations.ThreadSafe; +import main.java.com.javaedge.concurrency.annoations.ThreadSafe; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.atomic.AtomicReference; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/atomic/AtomicExample5.java b/src/main/java/com/javaedge/concurrency/atomic/AtomicExample5.java similarity index 87% rename from concurrency/src/main/java/com/javaedge/concurrency/example/atomic/AtomicExample5.java rename to src/main/java/com/javaedge/concurrency/atomic/AtomicExample5.java index f4cc64c..0c37a22 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/atomic/AtomicExample5.java +++ b/src/main/java/com/javaedge/concurrency/atomic/AtomicExample5.java @@ -1,6 +1,6 @@ -package com.javaedge.concurrency.example.atomic; +package main.java.com.javaedge.concurrency.atomic; -import com.javaedge.concurrency.annoations.ThreadSafe; +import main.java.com.javaedge.concurrency.annoations.ThreadSafe; import lombok.Getter; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/atomic/AtomicExample6.java b/src/main/java/com/javaedge/concurrency/atomic/AtomicExample6.java similarity index 92% rename from concurrency/src/main/java/com/javaedge/concurrency/example/atomic/AtomicExample6.java rename to src/main/java/com/javaedge/concurrency/atomic/AtomicExample6.java index 7d37d40..b5a4f7b 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/atomic/AtomicExample6.java +++ b/src/main/java/com/javaedge/concurrency/atomic/AtomicExample6.java @@ -1,6 +1,6 @@ -package com.javaedge.concurrency.example.atomic; +package main.java.com.javaedge.concurrency.atomic; -import com.javaedge.concurrency.annoations.ThreadSafe; +import main.java.com.javaedge.concurrency.annoations.ThreadSafe; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.CountDownLatch; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/atomic/AtomicTest.java b/src/main/java/com/javaedge/concurrency/atomic/AtomicTest.java similarity index 92% rename from concurrency/src/main/java/com/javaedge/concurrency/example/atomic/AtomicTest.java rename to src/main/java/com/javaedge/concurrency/atomic/AtomicTest.java index 5293174..8cbc04a 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/atomic/AtomicTest.java +++ b/src/main/java/com/javaedge/concurrency/atomic/AtomicTest.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.atomic; +package main.java.com.javaedge.concurrency.atomic; import java.util.concurrent.atomic.AtomicInteger; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/atomic/LockCASDemo.java b/src/main/java/com/javaedge/concurrency/atomic/LockCASDemo.java similarity index 97% rename from concurrency/src/main/java/com/javaedge/concurrency/example/atomic/LockCASDemo.java rename to src/main/java/com/javaedge/concurrency/atomic/LockCASDemo.java index 9c0e3d8..e7c03d9 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/atomic/LockCASDemo.java +++ b/src/main/java/com/javaedge/concurrency/atomic/LockCASDemo.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.atomic; +package main.java.com.javaedge.concurrency.atomic; import sun.misc.Unsafe; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/atomic/LongAccumulatorDemo.java b/src/main/java/com/javaedge/concurrency/atomic/LongAccumulatorDemo.java similarity index 95% rename from concurrency/src/main/java/com/javaedge/concurrency/example/atomic/LongAccumulatorDemo.java rename to src/main/java/com/javaedge/concurrency/atomic/LongAccumulatorDemo.java index dcdf135..d78dc47 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/atomic/LongAccumulatorDemo.java +++ b/src/main/java/com/javaedge/concurrency/atomic/LongAccumulatorDemo.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.atomic; +package main.java.com.javaedge.concurrency.atomic; import java.util.concurrent.atomic.LongAccumulator; import java.util.function.LongBinaryOperator; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/atomic/LongAdderDemo.java b/src/main/java/com/javaedge/concurrency/atomic/LongAdderDemo.java similarity index 97% rename from concurrency/src/main/java/com/javaedge/concurrency/example/atomic/LongAdderDemo.java rename to src/main/java/com/javaedge/concurrency/atomic/LongAdderDemo.java index 16927b1..b415904 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/atomic/LongAdderDemo.java +++ b/src/main/java/com/javaedge/concurrency/atomic/LongAdderDemo.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.atomic; +package main.java.com.javaedge.concurrency.atomic; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.LongAdder; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/cache/CacheController.java b/src/main/java/com/javaedge/concurrency/cache/CacheController.java similarity index 94% rename from concurrency/src/main/java/com/javaedge/concurrency/example/cache/CacheController.java rename to src/main/java/com/javaedge/concurrency/cache/CacheController.java index 1eb5898..321d024 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/cache/CacheController.java +++ b/src/main/java/com/javaedge/concurrency/cache/CacheController.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.cache; +package main.java.com.javaedge.concurrency.cache; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/cache/GuavaCacheExample1.java b/src/main/java/com/javaedge/concurrency/cache/GuavaCacheExample1.java similarity index 97% rename from concurrency/src/main/java/com/javaedge/concurrency/example/cache/GuavaCacheExample1.java rename to src/main/java/com/javaedge/concurrency/cache/GuavaCacheExample1.java index e66ca99..09d2bad 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/cache/GuavaCacheExample1.java +++ b/src/main/java/com/javaedge/concurrency/cache/GuavaCacheExample1.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.cache; +package com.javaedge.concurrency.cache; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/cache/GuavaCacheExample2.java b/src/main/java/com/javaedge/concurrency/cache/GuavaCacheExample2.java similarity index 97% rename from concurrency/src/main/java/com/javaedge/concurrency/example/cache/GuavaCacheExample2.java rename to src/main/java/com/javaedge/concurrency/cache/GuavaCacheExample2.java index 9c192ab..5548124 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/cache/GuavaCacheExample2.java +++ b/src/main/java/com/javaedge/concurrency/cache/GuavaCacheExample2.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.cache; +package main.java.com.javaedge.concurrency.cache; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/cache/RedisClient.java b/src/main/java/com/javaedge/concurrency/cache/RedisClient.java similarity index 94% rename from concurrency/src/main/java/com/javaedge/concurrency/example/cache/RedisClient.java rename to src/main/java/com/javaedge/concurrency/cache/RedisClient.java index cf12169..d985089 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/cache/RedisClient.java +++ b/src/main/java/com/javaedge/concurrency/cache/RedisClient.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.cache; +package main.java.com.javaedge.concurrency.cache; import org.springframework.stereotype.Component; import redis.clients.jedis.Jedis; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/cache/RedisConfig.java b/src/main/java/com/javaedge/concurrency/cache/RedisConfig.java similarity index 90% rename from concurrency/src/main/java/com/javaedge/concurrency/example/cache/RedisConfig.java rename to src/main/java/com/javaedge/concurrency/cache/RedisConfig.java index 1100ff7..7b7aaed 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/cache/RedisConfig.java +++ b/src/main/java/com/javaedge/concurrency/cache/RedisConfig.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.cache; +package main.java.com.javaedge.concurrency.cache; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/cas/demo/ConcurrentStack.java b/src/main/java/com/javaedge/concurrency/cas/demo/ConcurrentStack.java similarity index 96% rename from concurrency/src/main/java/com/javaedge/concurrency/cas/demo/ConcurrentStack.java rename to src/main/java/com/javaedge/concurrency/cas/demo/ConcurrentStack.java index 49129e3..97e53e9 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/cas/demo/ConcurrentStack.java +++ b/src/main/java/com/javaedge/concurrency/cas/demo/ConcurrentStack.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.cas.demo; +package main.java.com.javaedge.concurrency.cas.demo; import com.javaedge.concurrency.cas.demo.Node; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/cas/demo/Node.java b/src/main/java/com/javaedge/concurrency/cas/demo/Node.java similarity index 85% rename from concurrency/src/main/java/com/javaedge/concurrency/cas/demo/Node.java rename to src/main/java/com/javaedge/concurrency/cas/demo/Node.java index 8efedc0..14a1fa4 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/cas/demo/Node.java +++ b/src/main/java/com/javaedge/concurrency/cas/demo/Node.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.cas.demo; +package main.java.com.javaedge.concurrency.cas.demo; /** * 存储在栈里面元素 -- 对象 diff --git a/concurrency/src/main/java/com/javaedge/concurrency/cas/demo/Stack.java b/src/main/java/com/javaedge/concurrency/cas/demo/Stack.java similarity index 96% rename from concurrency/src/main/java/com/javaedge/concurrency/cas/demo/Stack.java rename to src/main/java/com/javaedge/concurrency/cas/demo/Stack.java index f118e6c..36b908e 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/cas/demo/Stack.java +++ b/src/main/java/com/javaedge/concurrency/cas/demo/Stack.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.cas.demo; +package main.java.com.javaedge.concurrency.cas.demo; import java.util.concurrent.TimeUnit; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/cas/demo/Test.java b/src/main/java/com/javaedge/concurrency/cas/demo/Test.java similarity index 92% rename from concurrency/src/main/java/com/javaedge/concurrency/cas/demo/Test.java rename to src/main/java/com/javaedge/concurrency/cas/demo/Test.java index fc6a42d..b90d2ac 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/cas/demo/Test.java +++ b/src/main/java/com/javaedge/concurrency/cas/demo/Test.java @@ -1,7 +1,7 @@ -package com.javaedge.concurrency.cas.demo; +package main.java.com.javaedge.concurrency.cas.demo; import com.javaedge.concurrency.cas.demo.Node; -import com.javaedge.concurrency.cas.demo.Stack; +import main.java.com.javaedge.concurrency.cas.demo.Stack; public class Test { public static void main(String[] args) throws InterruptedException { diff --git a/src/main/java/com/javaedge/concurrency/common/Nap.java b/src/main/java/com/javaedge/concurrency/common/Nap.java new file mode 100644 index 0000000..adb7c4c --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/common/Nap.java @@ -0,0 +1,23 @@ +package main.java.com.javaedge.concurrency.common; + +import java.util.concurrent.TimeUnit; + +/** + * @author JavaEdge + */ +public class Nap { + + // Seconds + public Nap(double t) { + try { + TimeUnit.MILLISECONDS.sleep((int) (1000 * t)); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + public Nap(double t, String msg) { + this(t); + System.out.println(msg); + } +} diff --git a/concurrency/src/main/java/com/javaedge/concurrency/common/Timer.java b/src/main/java/com/javaedge/concurrency/common/Timer.java similarity index 70% rename from concurrency/src/main/java/com/javaedge/concurrency/common/Timer.java rename to src/main/java/com/javaedge/concurrency/common/Timer.java index c6a857d..77a3da4 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/common/Timer.java +++ b/src/main/java/com/javaedge/concurrency/common/Timer.java @@ -2,13 +2,13 @@ // (c)2017 MindView LLC: see Copyright.txt // We make no guarantees that this code is fit for any purpose. // Visit http://OnJava8.com for more book information. -package com.javaedge.concurrency.common; +package main.java.com.javaedge.concurrency.common; import static java.util.concurrent.TimeUnit.NANOSECONDS; public class Timer { - private long start = System.nanoTime(); - public long duration() { + private static long start = System.nanoTime(); + public static long duration() { return NANOSECONDS.toMillis( System.nanoTime() - start); } @@ -17,4 +17,8 @@ public static long duration(Runnable test) { test.run(); return timer.duration(); } + + public static void main(String[] args) { + duration(); + } } diff --git a/concurrency/src/main/java/com/javaedge/concurrency/common/closure/ThreadClosure.java b/src/main/java/com/javaedge/concurrency/common/closure/ThreadClosure.java similarity index 95% rename from concurrency/src/main/java/com/javaedge/concurrency/common/closure/ThreadClosure.java rename to src/main/java/com/javaedge/concurrency/common/closure/ThreadClosure.java index d803764..eecd77a 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/common/closure/ThreadClosure.java +++ b/src/main/java/com/javaedge/concurrency/common/closure/ThreadClosure.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.common.closure; +package main.java.com.javaedge.concurrency.common.closure; import org.testng.annotations.Test; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/common/communication/ThreadCommunication.java b/src/main/java/com/javaedge/concurrency/common/communication/ThreadCommunication.java similarity index 94% rename from concurrency/src/main/java/com/javaedge/concurrency/common/communication/ThreadCommunication.java rename to src/main/java/com/javaedge/concurrency/common/communication/ThreadCommunication.java index 2203198..ba94398 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/common/communication/ThreadCommunication.java +++ b/src/main/java/com/javaedge/concurrency/common/communication/ThreadCommunication.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.common.communication; +package main.java.com.javaedge.concurrency.common.communication; import java.util.concurrent.locks.LockSupport; @@ -6,6 +6,7 @@ /** * 三种线程协作通信的方式:suspend/resume、wait/notify、park/unpark + * 原理文档:https://javaedge.blog.csdn.net/article/details/102345871 * * @author JavaEdge * @date 2019/10/8 @@ -40,7 +41,8 @@ public void suspendResumeTest() throws Exception { } /** - * 死锁的suspend/resume。 suspend并不会像wait一样释放锁,容易写出死锁代码 + * 死锁的suspend/resume + * suspend并不会像wait一样释放锁,容易写出死锁代码 */ @Test public void suspendResumeDeadLockTest() throws Exception { @@ -108,6 +110,7 @@ public void waitNotifyTest() throws Exception { try { System.out.println("1、进入等待"); this.wait(); + System.out.println("wait 结束!"); } catch (InterruptedException e) { e.printStackTrace(); } @@ -164,14 +167,15 @@ public void waitNotifyDeadLockTest() throws Exception { public void parkUnparkTest() throws Exception { // 启动线程 Thread consumerThread = new Thread(() -> { - if (bunShop == null) { // 如果没包子,则进入等待 + // 如果没包子,则进入等待 + if (bunShop == null) { System.out.println("1、进入等待"); LockSupport.park(); } System.out.println("2、买到包子,回家"); }); consumerThread.start(); - // 3秒之后,生产一个包子 + // 3s后,生产一个包子 Thread.sleep(3000L); bunShop = new Object(); LockSupport.unpark(consumerThread); diff --git a/concurrency/src/main/java/com/javaedge/concurrency/common/state/ThreadState.java b/src/main/java/com/javaedge/concurrency/common/state/ThreadState.java similarity index 97% rename from concurrency/src/main/java/com/javaedge/concurrency/common/state/ThreadState.java rename to src/main/java/com/javaedge/concurrency/common/state/ThreadState.java index e5172af..f123ad2 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/common/state/ThreadState.java +++ b/src/main/java/com/javaedge/concurrency/common/state/ThreadState.java @@ -1,7 +1,7 @@ -package com.javaedge.concurrency.common.state; +package main.java.com.javaedge.concurrency.common.state; /** - * 多线程运行状态切换示例 + * 多线程运行状态切换 * * @author JavaEdge * @date 2019/8/26 diff --git a/concurrency/src/main/java/com/javaedge/concurrency/common/stop/FlagStopThread.java b/src/main/java/com/javaedge/concurrency/common/stop/FlagStopThread.java similarity index 84% rename from concurrency/src/main/java/com/javaedge/concurrency/common/stop/FlagStopThread.java rename to src/main/java/com/javaedge/concurrency/common/stop/FlagStopThread.java index 8cfe920..7201e65 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/common/stop/FlagStopThread.java +++ b/src/main/java/com/javaedge/concurrency/common/stop/FlagStopThread.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.common.stop; +package main.java.com.javaedge.concurrency.common.stop; /** * 通过状态位来判断 @@ -7,6 +7,7 @@ * @date 2019/8/29 */ public class FlagStopThread extends Thread { + public volatile static boolean flag = true; public static void main(String[] args) throws InterruptedException { @@ -20,7 +21,7 @@ public static void main(String[] args) throws InterruptedException { e.printStackTrace(); } }).start(); - // 3秒之后,将状态标志改为False,代表不继续运行 + // 3s后,将状态标志改为False,代表不继续运行 Thread.sleep(3000L); flag = false; System.out.println("程序运行结束"); diff --git a/src/main/java/com/javaedge/concurrency/common/stop/PrimeGenerator.java b/src/main/java/com/javaedge/concurrency/common/stop/PrimeGenerator.java new file mode 100644 index 0000000..9ac8877 --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/common/stop/PrimeGenerator.java @@ -0,0 +1,70 @@ +package main.java.com.javaedge.concurrency.common.stop; + +import main.java.com.javaedge.concurrency.annoations.ThreadSafe; +import lombok.extern.slf4j.Slf4j; + +import javax.annotation.concurrent.GuardedBy; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static java.util.concurrent.TimeUnit.SECONDS; + +/** + * @author JavaEdge + * @date 2021/5/8 + */ +@ThreadSafe +@Slf4j +public class PrimeGenerator implements Runnable { + private static ExecutorService exec = Executors.newCachedThreadPool(); + + @GuardedBy("this") + private final List primes = new ArrayList<>(); + private volatile boolean cancelled; + + @Override + public void run() { + BigInteger p = BigInteger.ONE; + // 主循环在搜索下一个素数之前会首先检查取消标志 + while (!cancelled) { + // 持续枚举素数,直到被取消 + p = p.nextProbablePrime(); + synchronized (this) { + primes.add(p); + } + } + } + + public void cancel() { + cancelled = true; + } + + public synchronized List get() { + return new ArrayList<>(primes); + } + + static List aSecondOfPrimes() throws InterruptedException { + PrimeGenerator generator = new PrimeGenerator(); + exec.execute(generator); + try { + + /** + * 素数生成器通常并不会刚好在运行 1s 后停止,因为在 请求取消的时刻 和 run方法中循环执行下一次检查 之间可能存在延迟 + */ + SECONDS.sleep(1); + } finally { + // cancel方法由finally块调用,从而确保即使在调用sleep时被中断,也能取消素数生成器的执行 + // 如果cancel没有被调用,那么搜索素数的线程将永远运行下去,不断消耗CPU时钟周期,且使得JVM不能正常退出 + generator.cancel(); + } + return generator.get(); + } + + public static void main(String[] args) throws InterruptedException { + log.info("result:{}", aSecondOfPrimes()); + } +} + diff --git a/concurrency/src/main/java/com/javaedge/concurrency/common/stop/StopThread.java b/src/main/java/com/javaedge/concurrency/common/stop/StopThread.java similarity index 73% rename from concurrency/src/main/java/com/javaedge/concurrency/common/stop/StopThread.java rename to src/main/java/com/javaedge/concurrency/common/stop/StopThread.java index 3dfbd36..501b5b0 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/common/stop/StopThread.java +++ b/src/main/java/com/javaedge/concurrency/common/stop/StopThread.java @@ -1,8 +1,6 @@ -package com.javaedge.concurrency.common.stop; +package main.java.com.javaedge.concurrency.common.stop; /** - * 线程stop强制性中止,破坏线程安全的示例 - * * @author JavaEdge * @date 2019/8/26 */ @@ -15,7 +13,7 @@ public void run() { // 增加同步锁,确保线程安全 ++i; try { - // 休眠10秒,模拟耗时操作 + // 休眠10s,模拟耗时操作 Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); @@ -24,9 +22,6 @@ public void run() { } } - /** - * 打印i和j - */ public void print() { System.out.println("i=" + i + " j=" + j); } diff --git a/concurrency/src/main/java/com/javaedge/concurrency/common/stop/ThreadStop.java b/src/main/java/com/javaedge/concurrency/common/stop/ThreadStop.java similarity index 65% rename from concurrency/src/main/java/com/javaedge/concurrency/common/stop/ThreadStop.java rename to src/main/java/com/javaedge/concurrency/common/stop/ThreadStop.java index 288e5a9..6fe9aca 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/common/stop/ThreadStop.java +++ b/src/main/java/com/javaedge/concurrency/common/stop/ThreadStop.java @@ -1,8 +1,6 @@ -package com.javaedge.concurrency.common.stop; +package main.java.com.javaedge.concurrency.common.stop; /** - * 线程stop强制性中止,破坏线程安全的示例 - * * @author JavaEdge * @date 2019/8/26 */ @@ -12,9 +10,11 @@ public static void main(String[] args) throws InterruptedException { thread.start(); // 休眠1秒,确保i变量自增成功 Thread.sleep(1000); - // 暂停线程 - // thread.stop(); // 错误的终止 - thread.interrupt(); // 正确的终止 + // 错误的终止 线程stop强制性中止,破坏线程安全 +// thread.stop(); + + // 正确的终止 + thread.interrupt(); while (thread.isAlive()) { // 确保线程已经终止 } // 输出结果 diff --git a/concurrency/src/main/java/com/javaedge/concurrency/common/volatiletest/VisibilityDemo.java b/src/main/java/com/javaedge/concurrency/common/volatiletest/VisibilityDemo.java similarity index 96% rename from concurrency/src/main/java/com/javaedge/concurrency/common/volatiletest/VisibilityDemo.java rename to src/main/java/com/javaedge/concurrency/common/volatiletest/VisibilityDemo.java index 085d1d8..5247ab5 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/common/volatiletest/VisibilityDemo.java +++ b/src/main/java/com/javaedge/concurrency/common/volatiletest/VisibilityDemo.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.common.volatiletest; +package main.java.com.javaedge.concurrency.common.volatiletest; /** * @author JavaEdge diff --git a/concurrency/src/main/java/com/javaedge/concurrency/common/volatiletest/VisibilityDemo1.java b/src/main/java/com/javaedge/concurrency/common/volatiletest/VisibilityDemo1.java similarity index 93% rename from concurrency/src/main/java/com/javaedge/concurrency/common/volatiletest/VisibilityDemo1.java rename to src/main/java/com/javaedge/concurrency/common/volatiletest/VisibilityDemo1.java index 19169ba..8956eb2 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/common/volatiletest/VisibilityDemo1.java +++ b/src/main/java/com/javaedge/concurrency/common/volatiletest/VisibilityDemo1.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.common.volatiletest; +package main.java.com.javaedge.concurrency.common.volatiletest; import java.util.concurrent.TimeUnit; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/common/volatiletest/VisibilityDemo2.java b/src/main/java/com/javaedge/concurrency/common/volatiletest/VisibilityDemo2.java similarity index 94% rename from concurrency/src/main/java/com/javaedge/concurrency/common/volatiletest/VisibilityDemo2.java rename to src/main/java/com/javaedge/concurrency/common/volatiletest/VisibilityDemo2.java index edf43d4..04bb23a 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/common/volatiletest/VisibilityDemo2.java +++ b/src/main/java/com/javaedge/concurrency/common/volatiletest/VisibilityDemo2.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.common.volatiletest; +package main.java.com.javaedge.concurrency.common.volatiletest; import java.util.concurrent.TimeUnit; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/commonUnsafe/ArrayListExample.java b/src/main/java/com/javaedge/concurrency/commonunsafe/ArrayListExample.java similarity index 96% rename from concurrency/src/main/java/com/javaedge/concurrency/example/commonUnsafe/ArrayListExample.java rename to src/main/java/com/javaedge/concurrency/commonunsafe/ArrayListExample.java index b6c4b04..29541aa 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/commonUnsafe/ArrayListExample.java +++ b/src/main/java/com/javaedge/concurrency/commonunsafe/ArrayListExample.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.commonUnsafe; +package main.java.com.javaedge.concurrency.commonunsafe; import com.javaedge.concurrency.annoations.NotThreadSafe; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/commonUnsafe/DateFormatExample1.java b/src/main/java/com/javaedge/concurrency/commonunsafe/DateFormatExample1.java similarity index 96% rename from concurrency/src/main/java/com/javaedge/concurrency/example/commonUnsafe/DateFormatExample1.java rename to src/main/java/com/javaedge/concurrency/commonunsafe/DateFormatExample1.java index e560455..bceba91 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/commonUnsafe/DateFormatExample1.java +++ b/src/main/java/com/javaedge/concurrency/commonunsafe/DateFormatExample1.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.commonUnsafe; +package main.java.com.javaedge.concurrency.commonunsafe; import com.javaedge.concurrency.annoations.NotThreadSafe; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/commonUnsafe/DateFormatExample2.java b/src/main/java/com/javaedge/concurrency/commonunsafe/DateFormatExample2.java similarity index 96% rename from concurrency/src/main/java/com/javaedge/concurrency/example/commonUnsafe/DateFormatExample2.java rename to src/main/java/com/javaedge/concurrency/commonunsafe/DateFormatExample2.java index cfdcad9..809e505 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/commonUnsafe/DateFormatExample2.java +++ b/src/main/java/com/javaedge/concurrency/commonunsafe/DateFormatExample2.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.commonUnsafe; +package main.java.com.javaedge.concurrency.commonunsafe; import com.javaedge.concurrency.annoations.ThreadSafe; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/commonUnsafe/DateFormatExample3.java b/src/main/java/com/javaedge/concurrency/commonunsafe/DateFormatExample3.java similarity index 96% rename from concurrency/src/main/java/com/javaedge/concurrency/example/commonUnsafe/DateFormatExample3.java rename to src/main/java/com/javaedge/concurrency/commonunsafe/DateFormatExample3.java index c23d5fb..8057e44 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/commonUnsafe/DateFormatExample3.java +++ b/src/main/java/com/javaedge/concurrency/commonunsafe/DateFormatExample3.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.commonUnsafe; +package main.java.com.javaedge.concurrency.commonunsafe; import com.javaedge.concurrency.annoations.ThreadSafe; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/commonUnsafe/HashMapExample.java b/src/main/java/com/javaedge/concurrency/commonunsafe/HashMapExample.java similarity index 96% rename from concurrency/src/main/java/com/javaedge/concurrency/example/commonUnsafe/HashMapExample.java rename to src/main/java/com/javaedge/concurrency/commonunsafe/HashMapExample.java index 0220ee6..b6eb68b 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/commonUnsafe/HashMapExample.java +++ b/src/main/java/com/javaedge/concurrency/commonunsafe/HashMapExample.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.commonUnsafe; +package main.java.com.javaedge.concurrency.commonunsafe; import com.javaedge.concurrency.annoations.NotThreadSafe; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/commonUnsafe/HashSetExample.java b/src/main/java/com/javaedge/concurrency/commonunsafe/HashSetExample.java similarity index 96% rename from concurrency/src/main/java/com/javaedge/concurrency/example/commonUnsafe/HashSetExample.java rename to src/main/java/com/javaedge/concurrency/commonunsafe/HashSetExample.java index 8d1c90c..69b9a57 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/commonUnsafe/HashSetExample.java +++ b/src/main/java/com/javaedge/concurrency/commonunsafe/HashSetExample.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.commonUnsafe; +package main.java.com.javaedge.concurrency.commonunsafe; import com.javaedge.concurrency.annoations.NotThreadSafe; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/commonUnsafe/StringExample1.java b/src/main/java/com/javaedge/concurrency/commonunsafe/StringExample1.java similarity index 96% rename from concurrency/src/main/java/com/javaedge/concurrency/example/commonUnsafe/StringExample1.java rename to src/main/java/com/javaedge/concurrency/commonunsafe/StringExample1.java index fc41eb8..e445ff8 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/commonUnsafe/StringExample1.java +++ b/src/main/java/com/javaedge/concurrency/commonunsafe/StringExample1.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.commonUnsafe; +package main.java.com.javaedge.concurrency.commonunsafe; import com.javaedge.concurrency.annoations.NotThreadSafe; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/commonUnsafe/StringExample2.java b/src/main/java/com/javaedge/concurrency/commonunsafe/StringExample2.java similarity index 94% rename from concurrency/src/main/java/com/javaedge/concurrency/example/commonUnsafe/StringExample2.java rename to src/main/java/com/javaedge/concurrency/commonunsafe/StringExample2.java index 98c21ef..00594c1 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/commonUnsafe/StringExample2.java +++ b/src/main/java/com/javaedge/concurrency/commonunsafe/StringExample2.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.commonUnsafe; +package main.java.com.javaedge.concurrency.commonunsafe; import com.javaedge.concurrency.annoations.ThreadSafe; import lombok.extern.slf4j.Slf4j; @@ -8,6 +8,9 @@ import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; +/** + * @author JavaEdge + */ @Slf4j @ThreadSafe public class StringExample2 { diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/concurrent/ConcurrentHashMapExample.java b/src/main/java/com/javaedge/concurrency/concurrent/ConcurrentHashMapExample.java similarity index 96% rename from concurrency/src/main/java/com/javaedge/concurrency/example/concurrent/ConcurrentHashMapExample.java rename to src/main/java/com/javaedge/concurrency/concurrent/ConcurrentHashMapExample.java index b8c30c8..4a7d217 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/concurrent/ConcurrentHashMapExample.java +++ b/src/main/java/com/javaedge/concurrency/concurrent/ConcurrentHashMapExample.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.concurrent; +package main.java.com.javaedge.concurrency.concurrent; import com.javaedge.concurrency.annoations.ThreadSafe; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/concurrent/ConcurrentSkipListMapExample.java b/src/main/java/com/javaedge/concurrency/concurrent/ConcurrentSkipListMapExample.java similarity index 96% rename from concurrency/src/main/java/com/javaedge/concurrency/example/concurrent/ConcurrentSkipListMapExample.java rename to src/main/java/com/javaedge/concurrency/concurrent/ConcurrentSkipListMapExample.java index b81407e..1d39bd0 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/concurrent/ConcurrentSkipListMapExample.java +++ b/src/main/java/com/javaedge/concurrency/concurrent/ConcurrentSkipListMapExample.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.concurrent; +package main.java.com.javaedge.concurrency.concurrent; import com.javaedge.concurrency.annoations.ThreadSafe; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/concurrent/ConcurrentSkipListSetExample.java b/src/main/java/com/javaedge/concurrency/concurrent/ConcurrentSkipListSetExample.java similarity index 96% rename from concurrency/src/main/java/com/javaedge/concurrency/example/concurrent/ConcurrentSkipListSetExample.java rename to src/main/java/com/javaedge/concurrency/concurrent/ConcurrentSkipListSetExample.java index 1a1833c..b197d1b 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/concurrent/ConcurrentSkipListSetExample.java +++ b/src/main/java/com/javaedge/concurrency/concurrent/ConcurrentSkipListSetExample.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.concurrent; +package main.java.com.javaedge.concurrency.concurrent; import com.javaedge.concurrency.annoations.ThreadSafe; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/concurrent/CopyOnWriteArrayListExample.java b/src/main/java/com/javaedge/concurrency/concurrent/CopyOnWriteArrayListExample.java similarity index 96% rename from concurrency/src/main/java/com/javaedge/concurrency/example/concurrent/CopyOnWriteArrayListExample.java rename to src/main/java/com/javaedge/concurrency/concurrent/CopyOnWriteArrayListExample.java index a47d3d6..de26588 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/concurrent/CopyOnWriteArrayListExample.java +++ b/src/main/java/com/javaedge/concurrency/concurrent/CopyOnWriteArrayListExample.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.concurrent; +package main.java.com.javaedge.concurrency.concurrent; import com.javaedge.concurrency.annoations.ThreadSafe; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/concurrent/CopyOnWriteArraySetExample.java b/src/main/java/com/javaedge/concurrency/concurrent/CopyOnWriteArraySetExample.java similarity index 96% rename from concurrency/src/main/java/com/javaedge/concurrency/example/concurrent/CopyOnWriteArraySetExample.java rename to src/main/java/com/javaedge/concurrency/concurrent/CopyOnWriteArraySetExample.java index 29d6aad..7d9c882 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/concurrent/CopyOnWriteArraySetExample.java +++ b/src/main/java/com/javaedge/concurrency/concurrent/CopyOnWriteArraySetExample.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.concurrent; +package main.java.com.javaedge.concurrency.concurrent; import com.javaedge.concurrency.annoations.ThreadSafe; import lombok.extern.slf4j.Slf4j; diff --git a/src/main/java/com/javaedge/concurrency/condition/BlockedQueue.java b/src/main/java/com/javaedge/concurrency/condition/BlockedQueue.java new file mode 100644 index 0000000..75936aa --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/condition/BlockedQueue.java @@ -0,0 +1,58 @@ +package main.java.com.javaedge.concurrency.condition; + +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * @author JavaEdge + * @date 2021/4/21 + */ +public class BlockedQueue { + + final Lock lock = new ReentrantLock(); + + /** + * 条件变量:队列不满 + */ + final Condition notFull = lock.newCondition(); + + /** + * 条件变量:队列不空 + */ + final Condition notEmpty = lock.newCondition(); + + void enq(T x) { + lock.lock(); + try { +// while (队列已满) { + while (x!=null) { + // 等待队列不满 + notFull.await(); + } + // 省略入队操作 + // 入队后,通知可出队 + notEmpty.signal(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + lock.unlock(); + } + } + + void deq() throws InterruptedException { + lock.lock(); + try { +// while (队列已空) { + while (true) { + // 等待队列不空 + notEmpty.await(); + } + // 省略出队操作 + // 出队后,通知可入队 +// notFull.signal(); + } finally { + lock.unlock(); + } + } +} diff --git a/src/main/java/com/javaedge/concurrency/condition/DubboCondition.java b/src/main/java/com/javaedge/concurrency/condition/DubboCondition.java new file mode 100644 index 0000000..17f492c --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/condition/DubboCondition.java @@ -0,0 +1,85 @@ +package main.java.com.javaedge.concurrency.condition; + +import redis.clients.jedis.Response; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * @author JavaEdge + * @date 2021/4/21 + */ +public class DubboCondition { + + Response response; + /** + * 创建锁 + */ + private final Lock lock = new ReentrantLock(); + + /** + * 创建条件变量 + */ + private final Condition done = lock.newCondition(); + + /** + * 调用方通过该方法等待结果 + * + * @param timeout + * @return + */ + Object get(int timeout) throws TimeoutException { + long start = System.nanoTime(); + // 获取锁 + lock.lock(); + try { + while (!isDone()) { + // 获取锁后,通过经典的在循环中调用await()方法来实现等待。 + done.await(timeout, TimeUnit.SECONDS); + long cur = System.nanoTime(); + if (isDone() || + cur - start > timeout) { + break; + } + } + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + // 释放锁 + lock.unlock(); + } + if (!isDone()) { + throw new TimeoutException(); + } +// return returnFromResponse(); + return null; + } + + /** + * RPC结果是否已经返回 + * + * @return + */ + boolean isDone() { + return response != null; + } + + // RPC结果返回时调用该方法 + private void doReceived(Response res) { + // 获取锁 + lock.lock(); + try { + response = res; + if (done != null) { + // 通知调用线程,结果已经返回,不用继续等待 + done.signal(); + } + } finally { + // 释放锁 + lock.unlock(); + } + } +} diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/count/CountExample1.java b/src/main/java/com/javaedge/concurrency/count/CountExample1.java similarity index 91% rename from concurrency/src/main/java/com/javaedge/concurrency/example/count/CountExample1.java rename to src/main/java/com/javaedge/concurrency/count/CountExample1.java index 7cfc0c1..d3f4817 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/count/CountExample1.java +++ b/src/main/java/com/javaedge/concurrency/count/CountExample1.java @@ -1,6 +1,6 @@ -package com.javaedge.concurrency.example.count; +package main.java.com.javaedge.concurrency.count; -import com.javaedge.concurrency.annoations.NotThreadSafe; +import main.java.com.javaedge.concurrency.annoations.NotThreadSafe; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.CountDownLatch; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/count/CountExample2.java b/src/main/java/com/javaedge/concurrency/count/CountExample2.java similarity index 92% rename from concurrency/src/main/java/com/javaedge/concurrency/example/count/CountExample2.java rename to src/main/java/com/javaedge/concurrency/count/CountExample2.java index a386b11..5499fa8 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/count/CountExample2.java +++ b/src/main/java/com/javaedge/concurrency/count/CountExample2.java @@ -1,6 +1,6 @@ -package com.javaedge.concurrency.example.count; +package main.java.com.javaedge.concurrency.count; -import com.javaedge.concurrency.annoations.ThreadSafe; +import main.java.com.javaedge.concurrency.annoations.ThreadSafe; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.CountDownLatch; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/count/CountExample3.java b/src/main/java/com/javaedge/concurrency/count/CountExample3.java similarity index 91% rename from concurrency/src/main/java/com/javaedge/concurrency/example/count/CountExample3.java rename to src/main/java/com/javaedge/concurrency/count/CountExample3.java index 5a63a03..402cbdb 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/count/CountExample3.java +++ b/src/main/java/com/javaedge/concurrency/count/CountExample3.java @@ -1,6 +1,6 @@ -package com.javaedge.concurrency.example.count; +package main.java.com.javaedge.concurrency.count; -import com.javaedge.concurrency.annoations.ThreadSafe; +import main.java.com.javaedge.concurrency.annoations.ThreadSafe; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.CountDownLatch; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/count/CountExample4.java b/src/main/java/com/javaedge/concurrency/count/CountExample4.java similarity index 91% rename from concurrency/src/main/java/com/javaedge/concurrency/example/count/CountExample4.java rename to src/main/java/com/javaedge/concurrency/count/CountExample4.java index 0d961f0..a3b87ae 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/count/CountExample4.java +++ b/src/main/java/com/javaedge/concurrency/count/CountExample4.java @@ -1,6 +1,6 @@ -package com.javaedge.concurrency.example.count; +package main.java.com.javaedge.concurrency.count; -import com.javaedge.concurrency.annoations.NotThreadSafe; +import main.java.com.javaedge.concurrency.annoations.NotThreadSafe; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.CountDownLatch; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/deadLock/DeadLock.java b/src/main/java/com/javaedge/concurrency/deadLock/DeadLock.java similarity index 72% rename from concurrency/src/main/java/com/javaedge/concurrency/example/deadLock/DeadLock.java rename to src/main/java/com/javaedge/concurrency/deadLock/DeadLock.java index 304ce17..0719f17 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/deadLock/DeadLock.java +++ b/src/main/java/com/javaedge/concurrency/deadLock/DeadLock.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.deadLock; +package main.java.com.javaedge.concurrency.deadLock; import lombok.extern.slf4j.Slf4j; @@ -9,37 +9,46 @@ * td1睡眠结束后需要锁定o2才能继续执行,而此时o2已被td2锁定; * td2睡眠结束后需要锁定o1才能继续执行,而此时o1已被td1锁定; * td1、td2相互等待,都需要得到对方锁定的资源才能继续执行,从而死锁。 + * + * @author JavaEdge */ - @Slf4j public class DeadLock implements Runnable { + public int flag = 1; - //静态对象是类的所有对象共享的 - private static Object o1 = new Object(), o2 = new Object(); + + /** + * 静态对象是类的所有对象共享的 + */ + private static final Object O_1 = new Object(); + private static final Object O_2 = new Object(); @Override public void run() { + log.info("flag:{}", flag); + if (flag == 1) { - synchronized (o1) { + synchronized (O_1) { try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } - synchronized (o2) { + synchronized (O_2) { log.info("1"); } } } + if (flag == 0) { - synchronized (o2) { + synchronized (O_2) { try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } - synchronized (o1) { + synchronized (O_1) { log.info("0"); } } @@ -51,8 +60,8 @@ public static void main(String[] args) { DeadLock td2 = new DeadLock(); td1.flag = 1; td2.flag = 0; - //td1,td2都处于可执行状态,但JVM线程调度先执行哪个线程是不确定的。 - //td2的run()可能在td1的run()之前运行 + // td1,td2都处于可执行状态,但JVM线程调度先执行哪个线程是不确定的 + // td2的run()可能在td1的run()之前运行 new Thread(td1).start(); new Thread(td2).start(); } diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/ForkJoinTaskExample.java b/src/main/java/com/javaedge/concurrency/forkjoin/ForkJoinTaskExample.java similarity index 86% rename from concurrency/src/main/java/com/javaedge/concurrency/example/aqs/ForkJoinTaskExample.java rename to src/main/java/com/javaedge/concurrency/forkjoin/ForkJoinTaskExample.java index 5380f90..58b2c59 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/ForkJoinTaskExample.java +++ b/src/main/java/com/javaedge/concurrency/forkjoin/ForkJoinTaskExample.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.aqs; +package main.java.com.javaedge.concurrency.forkjoin; import lombok.extern.slf4j.Slf4j; @@ -6,10 +6,13 @@ import java.util.concurrent.Future; import java.util.concurrent.RecursiveTask; +/** + * @author JavaEdge + */ @Slf4j public class ForkJoinTaskExample extends RecursiveTask { - public static final int threshold = 2; + public static final int THRESHOLD = 2; private int start; private int end; @@ -23,7 +26,7 @@ protected Integer compute() { int sum = 0; //如果任务足够小就计算任务 - boolean canCompute = (end - start) <= threshold; + boolean canCompute = (end - start) <= THRESHOLD; if (canCompute) { for (int i = start; i <= end; i++) { sum += i; @@ -51,10 +54,10 @@ protected Integer compute() { public static void main(String[] args) { ForkJoinPool forkjoinPool = new ForkJoinPool(); - //生成一个计算任务,计算1+2+3+4 + // 生成一个计算任务,计算1+2+3+4 ForkJoinTaskExample task = new ForkJoinTaskExample(1, 100); - //执行一个任务 + // 执行一个任务 Future result = forkjoinPool.submit(task); try { diff --git a/src/main/java/com/javaedge/concurrency/forkjoin/ForkJoinTaskExample2.java b/src/main/java/com/javaedge/concurrency/forkjoin/ForkJoinTaskExample2.java new file mode 100755 index 0000000..4621040 --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/forkjoin/ForkJoinTaskExample2.java @@ -0,0 +1,52 @@ +package main.java.com.javaedge.concurrency.forkjoin; + +import lombok.extern.slf4j.Slf4j; + +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.RecursiveTask; + +/** + * @author JavaEdge + */ +@Slf4j +public class ForkJoinTaskExample2 { + public static void main(String[] args) { + // 创建分治任务线程池 + ForkJoinPool forkJoinPool = new ForkJoinPool(4); + + // 创建分治任务 + Fibonacci fib = new Fibonacci(30); + + // 启动分治任务 + Integer result = forkJoinPool.invoke(fib); + + System.out.println(result); + } + + /** + * 数列的递归任务 需要有返回值 + */ + static class Fibonacci extends RecursiveTask { + final int n; + + Fibonacci(int n) { + this.n = n; + } + + @Override + protected Integer compute() { + if (n <= 1) { + return n; + } + + Fibonacci f1 = new Fibonacci(n - 1); + + // 创建子任务 + f1.fork(); + Fibonacci f2 = new Fibonacci(n - 2); + + // 等待子任务结果,并合并结果 + return f2.compute() + f1.join(); + } + } +} diff --git a/src/main/java/com/javaedge/concurrency/forkjoin/ForkJoinTaskExample3.java b/src/main/java/com/javaedge/concurrency/forkjoin/ForkJoinTaskExample3.java new file mode 100755 index 0000000..a33e195 --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/forkjoin/ForkJoinTaskExample3.java @@ -0,0 +1,193 @@ +package main.java.com.javaedge.concurrency.forkjoin; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.RecursiveTask; + +/** + * @author JavaEdge + */ +@Slf4j +public class ForkJoinTaskExample3 { + + public static void main(String[] args) { + String[] fc = {"hello world", + "hello me", + "hello fork", + "hello join", + "fork join in world"}; + //创建ForkJoin线程池 + ForkJoinPool fjp = new ForkJoinPool(3); + //创建任务 + MR mr = new MR(fc, 0, fc.length); + //启动任务 + Map result = fjp.invoke(mr); + //输出结果 + result.forEach((k, v) -> System.out.println(k + ":" + v)); + } + + /** + * MR模拟类 + */ + static class MR extends RecursiveTask> { + private String[] fc; + private int start, end; + + /** + * 构造函数 + * + * @param fc + * @param fr + * @param to + */ + MR(String[] fc, int fr, int to) { + this.fc = fc; + this.start = fr; + this.end = to; + } + + @Override + protected Map compute() { + if (end - start == 1) { + return calc(fc[start]); + } else { + int mid = (start + end) / 2; + MR mr1 = new MR(fc, start, mid); + // 前半部分数据fork一个递归任务去处理 + mr1.fork(); + MR mr2 = new MR(fc, mid, end); + //计算子任务,并返回合并的结果 后半部分数据则在当前任务中递归处理:mr2.compute() + // 如果join在前面会先首先让当前线程阻塞在join()上。当join()执行完才会执行mr2.compute(),这样并行度会降低 + /** + * 为什么不能merge mr1.compute和mr2..compute或者mr1.join和mr2的join呢? + * compute+compute相当于没用forkjoin,都在一个线程里跑的。 + * 如果用join+join也可以,不过jdk官方有个建议,顺序要用:a.fork(); b.fork(); b.join(); a.join();否则性能有问题。 + * 所以还是用fork+compute更简单 + */ + return merge(mr2.compute(), mr1.join()); + } + } + + /** + * 合并结果 + * + * @param r1 + * @param r2 + * @return + */ + private Map merge( + Map r1, + Map r2) { + Map result = new HashMap<>(); + result.putAll(r1); + //合并结果 + r2.forEach((k, v) -> { + Long c = result.get(k); + if (c != null) { + result.put(k, c + v); + } else { + result.put(k, v); + } + }); + return result; + } + + //统计单词数量 + private Map + calc(String line) { + Map result = + new HashMap<>(); + //分割单词 + String[] words = + line.split("\\s+"); + //统计单词数量 + for (String w : words) { + Long v = result.get(w); + if (v != null) { + result.put(w, v + 1); + } else { + result.put(w, 1L); + } + } + return result; + } + } + + /** + * Ryzen 1700 8核16线程 3.0 GHz + */ + @Test + public void mergeSort() { + long[] arrs = new long[100000000]; + for (int i = 0; i < 100000000; i++) { + arrs[i] = (long) (Math.random() * 100000000); + } + long startTime = System.currentTimeMillis(); + ForkJoinPool forkJoinPool = new ForkJoinPool(Runtime.getRuntime().availableProcessors()); + MergeSort mergeSort = new MergeSort(arrs); +// arrs = forkJoinPool.invoke(mergeSort); + //传统递归 + arrs = mergeSort(arrs); + long endTime = System.currentTimeMillis(); + System.out.println("耗时:" + (endTime - startTime)); + } + + /** + * 传统递归 + * 耗时: + */ + public static long[] mergeSort(long[] arrs) { + if (arrs.length < 2) { + return arrs; + } + int mid = arrs.length / 2; + long[] left = Arrays.copyOfRange(arrs, 0, mid); + long[] right = Arrays.copyOfRange(arrs, mid, arrs.length); + return merge(mergeSort(left), mergeSort(right)); + } + + public static long[] merge(long[] left, long[] right) { + long[] result = new long[left.length + right.length]; + for (int i = 0, m = 0, j = 0; m < result.length; m++) { + if (i >= left.length) { + result[m] = right[j++]; + } else if (j >= right.length) { + result[m] = left[i++]; + } else if (left[i] > right[j]) { + result[m] = right[j++]; + } else { + result[m] = left[i++]; + } + } + return result; + } + + /** + * fork/join + * 耗时:14853 ms + */ + class MergeSort extends RecursiveTask { + long[] arrs; + + public MergeSort(long[] arrs) { + this.arrs = arrs; + } + + @Override + protected long[] compute() { + if (arrs.length < 2) { + return arrs; + } + int mid = arrs.length / 2; + MergeSort left = new MergeSort(Arrays.copyOfRange(arrs, 0, mid)); + left.fork(); + MergeSort right = new MergeSort(Arrays.copyOfRange(arrs, mid, arrs.length)); + return merge(right.compute(), left.join()); + } + } +} diff --git a/src/main/java/com/javaedge/concurrency/furure/guava/FutureExample.java b/src/main/java/com/javaedge/concurrency/furure/guava/FutureExample.java new file mode 100755 index 0000000..8af249d --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/furure/guava/FutureExample.java @@ -0,0 +1,52 @@ +package main.java.com.javaedge.concurrency.furure.guava; + +import com.google.common.util.concurrent.*; +import lombok.extern.slf4j.Slf4j; + +import javax.annotation.Nullable; +import java.util.concurrent.Callable; +import java.util.concurrent.Executors; + +/** + * @author JavaEdge + */ +@Slf4j +public class FutureExample { + + static class MyCallable implements Callable { + + @Override + public String call() throws Exception { + log.info("do something in callable"); + Thread.sleep(5000); + return "Done"; + } + } + + public static void main(String[] args) throws Exception { + // 装饰器模式 + ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(2)); + + ListenableFuture future = service.submit(new MyCallable()); + + System.out.println(future.hashCode()); + + // 异步非阻塞:观察者模式 当ListenableFuture完成时,需要执行的程序 + Futures.addCallback(future, new FutureCallback() { + @Override + public void onSuccess(@Nullable String s) { + + } + + @Override + public void onFailure(Throwable throwable) { + throwable.printStackTrace(); + } + }, service); + + log.info("do something in main"); + Thread.sleep(1000); + String result = future.get(); + log.info("result:{}", result); + } +} diff --git a/src/main/java/com/javaedge/concurrency/furure/jdk/CompletableFurureDemo3.java b/src/main/java/com/javaedge/concurrency/furure/jdk/CompletableFurureDemo3.java new file mode 100644 index 0000000..d913677 --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/furure/jdk/CompletableFurureDemo3.java @@ -0,0 +1,65 @@ +package main.java.com.javaedge.concurrency.furure.jdk; + +import org.junit.Test; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.concurrent.*; +import java.util.concurrent.locks.LockSupport; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * @author JavaEdge + * @date 2022/5/28 + */ +public class CompletableFurureDemo3 { + + @Test + public void CompletableFutureAndExecutor() { + Stream integerStream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + ExecutorService executor = Executors.newFixedThreadPool((int) integerStream.count()); + List> futureList = integerStream + .map(operand -> + CompletableFuture.supplyAsync(() -> { + getThreadName(); + return 1; + }, executor + ) + ).collect(Collectors.toList()); + long count = futureList.stream().map(CompletableFuture::join).count(); + System.out.println(count); + } + + /** + * 使用CountDownLatch改造主线程阻塞直到任务都完成 + * @throws InterruptedException + */ + @Test + public void CompletableFutureAndExecutor2() throws InterruptedException { + Stream integerStream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + CountDownLatch countDownLatch = new CountDownLatch(10); + ExecutorService executor = Executors.newFixedThreadPool(10); +// ExecutorService executor = Executors.newFixedThreadPool((int) integerStream.count()); FIXME bug写法 + List> futureList = integerStream + .map(operand -> + CompletableFuture.supplyAsync(() -> { + getThreadName(); + countDownLatch.countDown(); + return 1; + }, executor + ) + ).collect(Collectors.toList()); + countDownLatch.await(10, TimeUnit.MINUTES); + long count = futureList.stream().map(CompletableFuture::join).count(); + System.out.println(count); + } + + private void getThreadName() { + // sleep 1秒 + LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1)); + String time = LocalDateTime.now().toLocalTime().toString(); + String name = Thread.currentThread().getName(); + System.out.println(time + " " + name); + } +} diff --git a/src/main/java/com/javaedge/concurrency/furure/jdk/CompletableFutureDemo.java b/src/main/java/com/javaedge/concurrency/furure/jdk/CompletableFutureDemo.java new file mode 100644 index 0000000..47e25f1 --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/furure/jdk/CompletableFutureDemo.java @@ -0,0 +1,56 @@ +package main.java.com.javaedge.concurrency.furure.jdk; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import java.util.concurrent.*; + +/** + * @author JavaEdge + * @date 2021/4/15 + */ +@Slf4j +public class CompletableFutureDemo { + + @AllArgsConstructor + private static class MyTask implements Callable { + + private String name; + private int timeInSeconds; + private boolean ret; + + @Override + public Boolean call() { + // 模拟业务执行时间 + // 实际中时间不固定,可能在处理计算任务, + try { + Thread.sleep(timeInSeconds); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println(name + " task callback"); + return ret; + } + } + + public static void main(String[] args) throws Exception { + MyTask task1 = new MyTask("task1", 3, true); + MyTask task2 = new MyTask("task2", 4, true); + MyTask task3 = new MyTask("task3", 1, false); + + CompletableFuture f1 = CompletableFuture.supplyAsync(task1::call).thenAccept((result) -> callback(result)); + + CompletableFuture f2 = CompletableFuture.supplyAsync(task2::call).thenAccept((result) -> callback(result)); + + CompletableFuture f3 = CompletableFuture.supplyAsync(task3::call).thenAccept((result) -> callback(result)); + + System.in.read(); + } + + private static void callback(Boolean result) { + if (!result) { + // 处理结束流程 通知其他线程结束(回滚) 超时处理 + System.exit(0); + } + } +} diff --git a/src/main/java/com/javaedge/concurrency/furure/jdk/CompletableFutureDemo2.java b/src/main/java/com/javaedge/concurrency/furure/jdk/CompletableFutureDemo2.java new file mode 100644 index 0000000..b8714e7 --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/furure/jdk/CompletableFutureDemo2.java @@ -0,0 +1,65 @@ +package main.java.com.javaedge.concurrency.furure.jdk; + +import lombok.extern.slf4j.Slf4j; + +import java.util.Random; +import java.util.concurrent.CompletableFuture; + +/** + * @author JavaEdge + * @date 2021/4/15 + */ +@Slf4j +public class CompletableFutureDemo2 { + + public static void main(String[] args) throws Exception { + CompletableFuture future1 = CompletableFuture + // 1 + .supplyAsync(() -> "Hello World") + // 2 + .thenApply(s -> s + " Java") + // 3 + .thenApply(String::toUpperCase); + System.out.println(future1.join()); + +// CompletableFuture future2 = CompletableFuture +// .supplyAsync(() -> (1 / 0)) +// .thenApply(r -> r * 2); +// System.out.println(future2.join()); + + CompletableFuture future3 = CompletableFuture + .supplyAsync(() -> 1 / 0) + .thenApply(r -> r * 2) + .exceptionally(e -> 0); + System.out.println(future3.join()); + + Random rand = new Random(47); + CompletableFuture f1 = + CompletableFuture.supplyAsync(() -> { + int t = rand.nextInt(20); + try { + Thread.sleep(t); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return String.valueOf(t); + }); + + CompletableFuture f2 = + CompletableFuture.supplyAsync(() -> { + int t = rand.nextInt(); + try { + Thread.sleep(t); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return String.valueOf(t); + }); + + CompletableFuture f3 = + f1.applyToEither(f2, s -> s); + + System.out.println(f3.join()); + + } +} diff --git a/src/main/java/com/javaedge/concurrency/furure/jdk/CompletionServiceDemo.java b/src/main/java/com/javaedge/concurrency/furure/jdk/CompletionServiceDemo.java new file mode 100644 index 0000000..76cb04b --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/furure/jdk/CompletionServiceDemo.java @@ -0,0 +1,144 @@ +package main.java.com.javaedge.concurrency.furure.jdk; + +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicReference; + +/** + * @author JavaEdge + * @date 2021/4/18 + */ +public class CompletionServiceDemo { + +// public static void main(String[] args) throws InterruptedException, ExecutionException { +// test1(); +// +// test2(); +// +// test3(); +// } + + public static void main(String[] args) throws ExecutionException, InterruptedException { + test0(); + } + + private static void test0() throws ExecutionException, InterruptedException { + ExecutorService executor = Executors.newFixedThreadPool(3); + Future f1 = executor.submit(() -> getPrice1()); + Future f2 = executor.submit(() -> getPrice2()); + Future f3 = executor.submit(() -> getPrice3()); + + executor.execute(() -> { + try { + save(f1.get()); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } + }); + executor.execute(() -> { + try { + save(f2.get()); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } + }); + executor.execute(() -> { + try { + save(f3.get()); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } + }); + f3.get(); + } + + private static AtomicReference test3() { + + ExecutorService executor = Executors.newFixedThreadPool(3); + CompletionService completionService = new ExecutorCompletionService<>(executor); + + // 异步查询价格 + completionService.submit(CompletionServiceDemo::getPrice1); + completionService.submit(CompletionServiceDemo::getPrice2); + completionService.submit(CompletionServiceDemo::getPrice3); + // 将查询结果异步保存 + // 并计算最低价格 + AtomicReference m = new AtomicReference<>(Integer.MAX_VALUE); + for (int i = 0; i < 3; i++) { + executor.execute(() -> { + Integer r = null; + try { + r = completionService.take().get(); + } catch (Exception e) { + e.printStackTrace(); + } + save(r); + m.set(Integer.min(m.get(), r)); + }); + } + return m; + } + + private static void test2() throws InterruptedException, ExecutionException { + ExecutorService executor = Executors.newFixedThreadPool(3); + CompletionService cs = new ExecutorCompletionService<>(executor); + + // 异步查询 + cs.submit(CompletionServiceDemo::getPrice1); + cs.submit(CompletionServiceDemo::getPrice2); + cs.submit(CompletionServiceDemo::getPrice3); + + // 将结果异步保存 + for (int i = 0; i < 3; i++) { + Integer r = cs.take().get(); + executor.execute(() -> save(r)); + } + } + + private static void test1() throws ExecutionException, InterruptedException { + + ExecutorService executor = Executors.newFixedThreadPool(3); + + // 异步查询 + Future f1 = executor.submit(CompletionServiceDemo::getPrice1); + + Future f2 = executor.submit(CompletionServiceDemo::getPrice2); + + Future f3 = executor.submit(CompletionServiceDemo::getPrice3); + + Integer r; + // 获取各个价格并保存 + r = f1.get(); + Integer finalR = r; + executor.execute(() -> save(finalR)); + + r = f2.get(); + Integer finalR1 = r; + executor.execute(() -> save(finalR1)); + + r = f3.get(); + Integer finalR2 = r; + executor.execute(() -> save(finalR2)); + } + + private static void save(Integer r) { + System.out.println("r" + r); + } + + private static Integer getPrice3() { + return 3; + } + + private static Integer getPrice2() { + return 2; + } + + private static Integer getPrice1() { + return 1; + } +} diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/FutureExample.java b/src/main/java/com/javaedge/concurrency/furure/jdk/FutureExample.java similarity index 91% rename from concurrency/src/main/java/com/javaedge/concurrency/example/aqs/FutureExample.java rename to src/main/java/com/javaedge/concurrency/furure/jdk/FutureExample.java index 54781b7..68623dc 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/FutureExample.java +++ b/src/main/java/com/javaedge/concurrency/furure/jdk/FutureExample.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.aqs; +package main.java.com.javaedge.concurrency.furure.jdk; import lombok.extern.slf4j.Slf4j; @@ -7,6 +7,9 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; +/** + * @author JavaEdge + */ @Slf4j public class FutureExample { diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/FutureTaskExample.java b/src/main/java/com/javaedge/concurrency/furure/jdk/FutureTaskExample.java similarity index 78% rename from concurrency/src/main/java/com/javaedge/concurrency/example/aqs/FutureTaskExample.java rename to src/main/java/com/javaedge/concurrency/furure/jdk/FutureTaskExample.java index 2d41e2d..9f7f70e 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/aqs/FutureTaskExample.java +++ b/src/main/java/com/javaedge/concurrency/furure/jdk/FutureTaskExample.java @@ -1,14 +1,18 @@ -package com.javaedge.concurrency.example.aqs; +package main.java.com.javaedge.concurrency.furure.jdk; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; +/** + * @author JavaEdge + */ @Slf4j public class FutureTaskExample { public static void main(String[] args) throws Exception { + // 创建异步任务 FutureTask futureTask = new FutureTask(new Callable() { @Override public String call() throws Exception { @@ -17,10 +21,11 @@ public String call() throws Exception { return "Done"; } }); - + // 启动线程 new Thread(futureTask).start(); log.info("do something in main"); Thread.sleep(1000); + // 【阻塞】等待任务执行完毕,并返回结果 String result = futureTask.get(); log.info("result:{}", result); } diff --git a/src/main/java/com/javaedge/concurrency/furure/jdk/Machina.java b/src/main/java/com/javaedge/concurrency/furure/jdk/Machina.java new file mode 100644 index 0000000..3ddb7e1 --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/furure/jdk/Machina.java @@ -0,0 +1,43 @@ +package main.java.com.javaedge.concurrency.furure.jdk; + + +import com.javaedge.concurrency.common.Nap; + +/** + * @author JavaEdge + */ +public class Machina { + + public enum State { + START, ONE, TWO, THREE, END; + + State step() { + if (equals(END)) { + return END; + } + return values()[ordinal() + 1]; + } + } + + private State state = State.START; + private final int id; + + public Machina(int id) { + this.id = id; + } + + public static Machina work(Machina m) { + if (!m.state.equals(State.END)) { + new Nap(0.1); + m.state = m.state.step(); + } + System.out.println(m); + return m; + } + + @Override + public String toString() { + return "Machina" + id + ": " + + (state.equals(State.END) ? "complete" : state); + } +} diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/immutable/ImmutableExample1.java b/src/main/java/com/javaedge/concurrency/immutable/ImmutableExample1.java similarity index 84% rename from concurrency/src/main/java/com/javaedge/concurrency/example/immutable/ImmutableExample1.java rename to src/main/java/com/javaedge/concurrency/immutable/ImmutableExample1.java index 5797992..8d83363 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/immutable/ImmutableExample1.java +++ b/src/main/java/com/javaedge/concurrency/immutable/ImmutableExample1.java @@ -1,7 +1,7 @@ -package com.javaedge.concurrency.example.immutable; +package main.java.com.javaedge.concurrency.immutable; import com.google.common.collect.Maps; -import com.javaedge.concurrency.annoations.NotThreadSafe; +import main.java.com.javaedge.concurrency.annoations.NotThreadSafe; import lombok.extern.slf4j.Slf4j; import java.util.Map; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/immutable/ImmutableExample2.java b/src/main/java/com/javaedge/concurrency/immutable/ImmutableExample2.java similarity index 80% rename from concurrency/src/main/java/com/javaedge/concurrency/example/immutable/ImmutableExample2.java rename to src/main/java/com/javaedge/concurrency/immutable/ImmutableExample2.java index 126cbf5..5ac8089 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/immutable/ImmutableExample2.java +++ b/src/main/java/com/javaedge/concurrency/immutable/ImmutableExample2.java @@ -1,7 +1,7 @@ -package com.javaedge.concurrency.example.immutable; +package main.java.com.javaedge.concurrency.immutable; import com.google.common.collect.Maps; -import com.javaedge.concurrency.annoations.ThreadSafe; +import main.java.com.javaedge.concurrency.annoations.ThreadSafe; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/immutable/ImmutableExample3.java b/src/main/java/com/javaedge/concurrency/immutable/ImmutableExample3.java similarity index 85% rename from concurrency/src/main/java/com/javaedge/concurrency/example/immutable/ImmutableExample3.java rename to src/main/java/com/javaedge/concurrency/immutable/ImmutableExample3.java index 587cd2d..9c88b70 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/immutable/ImmutableExample3.java +++ b/src/main/java/com/javaedge/concurrency/immutable/ImmutableExample3.java @@ -1,9 +1,9 @@ -package com.javaedge.concurrency.example.immutable; +package main.java.com.javaedge.concurrency.immutable; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; -import com.javaedge.concurrency.annoations.ThreadSafe; +import main.java.com.javaedge.concurrency.annoations.ThreadSafe; @ThreadSafe public class ImmutableExample3 { diff --git a/src/main/java/com/javaedge/concurrency/lock/Account.java b/src/main/java/com/javaedge/concurrency/lock/Account.java new file mode 100644 index 0000000..b45f34e --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/lock/Account.java @@ -0,0 +1,71 @@ +package main.java.com.javaedge.concurrency.lock; + +import java.util.Random; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + + +/** + * @author JavaEdge + * @date 2021/4/21 + */ +class Account { + + private int balance; + + private final Lock lock = new ReentrantLock(); + + /** + * 转账 + * + * @param target 目标账户 + * @param amount 转账金额 + */ + void errorTransfer(Account target, int amount) { + while (true) { + if (this.lock.tryLock()) { + try { + if (target.lock.tryLock()) { + try { + this.balance -= amount; + target.balance += amount; + } finally { + target.lock.unlock(); + } + } else { + // nothing + } + } finally { + this.lock.unlock(); + } + } else { + // nothing + } + } + } + + void correctTransfer(Account tar, int amt) throws InterruptedException { + while (true) { + if (this.lock.tryLock(new Random().nextLong(), TimeUnit.NANOSECONDS)) { + try { + if (tar.lock.tryLock(new Random().nextLong(), TimeUnit.NANOSECONDS)) { + try { + this.balance -= amt; + tar.balance += amt; + break; + } finally { + tar.lock.unlock(); + } + } else { + // nothing + } + } finally { + this.lock.unlock(); + } + } else { + // nothing + } + } + } +} diff --git a/src/main/java/com/javaedge/concurrency/lock/CacheDemo1.java b/src/main/java/com/javaedge/concurrency/lock/CacheDemo1.java new file mode 100644 index 0000000..aa7cea3 --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/lock/CacheDemo1.java @@ -0,0 +1,46 @@ +package main.java.com.javaedge.concurrency.lock; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * @author JavaEdge + * @date 2021/4/22 + */ +public class CacheDemo1 { + + final Map m = new HashMap(); + + final ReadWriteLock rwl = new ReentrantReadWriteLock(); + + final Lock r = rwl.readLock(); + + final Lock w = rwl.writeLock(); + + Data get(String key) { + r.lock(); + try { + return m.get(key); + } finally { + r.unlock(); + } + } + + Data put(String key, Data v) { + w.lock(); + try { + return m.put(key, v); + } finally { + w.unlock(); + } + } + + class Data { } + + public static void main(String[] args) { + + } +} diff --git a/src/main/java/com/javaedge/concurrency/lock/CacheDemo2.java b/src/main/java/com/javaedge/concurrency/lock/CacheDemo2.java new file mode 100644 index 0000000..5685fb2 --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/lock/CacheDemo2.java @@ -0,0 +1,72 @@ +package main.java.com.javaedge.concurrency.lock; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * @author JavaEdge + * @date 2021/4/22 + */ +public class CacheDemo2 { + + public static void main(String[] args) { + } + + final Map m = new HashMap<>(); + final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); + final Lock readLock = readWriteLock.readLock(); + final Lock writeLock = readWriteLock.writeLock(); + + V get(K key) { + V v = null; + // 1.加读锁 + readLock.lock(); + try { + // 2.读缓存 + v = m.get(key); + if (v == null) { + writeLock.lock(); + try { + // 再次验证并更新缓存 + } finally { + writeLock.unlock(); + } + } + } finally { + // 3.释放锁 + readLock.unlock(); + } + // 4.缓存中存在,返回 + if (v != null) { + return v; + } + + /** + * 5.若缓存中没有缓存目标对象,就需要从 DB 加载,然后写入缓存. + * 写缓存需要用到写锁 + */ + writeLock.lock(); + try { + + /** + * 6. + * 获取写锁后,并非直接去查询DB. + * 先再验证一次缓存中是否存在,因为高并发场景下,其他线程可能已查询过 DB + */ + v = m.get(key); + // 7 + if (v == null) { + // 再次验证如果还是不存在,才去查询DB + v = null; + // 并更新本地缓存 + m.put(key, v); + } + } finally { + writeLock.unlock(); + } + return v; + } +} diff --git a/src/main/java/com/javaedge/concurrency/lock/CacheDemo3.java b/src/main/java/com/javaedge/concurrency/lock/CacheDemo3.java new file mode 100644 index 0000000..fb3be1e --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/lock/CacheDemo3.java @@ -0,0 +1,59 @@ +package main.java.com.javaedge.concurrency.lock; + +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * @author JavaEdge + * @date 2021/4/22 + */ +public class CacheDemo3 { + + Object data; + + volatile boolean cacheValid; + + final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); + + final Lock readLock = readWriteLock.readLock(); + + final Lock writeLock = readWriteLock.writeLock(); + + void processCachedData() { + // 获取读锁 + readLock.lock(); + if (!cacheValid) { + // 释放读锁,因为不允许读锁的升级 + readLock.unlock(); + // 获取写锁 + writeLock.lock(); + try { + // 再次检查状态 + if (!cacheValid) { + // 省略具体代码 + data = null; + cacheValid = true; + } + /** + * 1.获取读锁的时候线程还是持有写锁的 + * 释放写锁前,降级为读锁 + * 这种锁的降级是支持的 + */ + readLock.lock(); + } finally { + // 释放写锁 + writeLock.unlock(); + } + } + // 此处仍持有读锁 + try { + use(data); + } finally { + readLock.unlock(); + } + } + + private void use(Object data) { + } +} \ No newline at end of file diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/lock/LockDemo.java b/src/main/java/com/javaedge/concurrency/lock/LockDemo.java similarity index 92% rename from concurrency/src/main/java/com/javaedge/concurrency/example/lock/LockDemo.java rename to src/main/java/com/javaedge/concurrency/lock/LockDemo.java index eb9f657..c7ae504 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/lock/LockDemo.java +++ b/src/main/java/com/javaedge/concurrency/lock/LockDemo.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.lock; +package main.java.com.javaedge.concurrency.lock; /** * 多线程 原子性 diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/lock/LockExample1.java b/src/main/java/com/javaedge/concurrency/lock/LockExample1.java similarity index 92% rename from concurrency/src/main/java/com/javaedge/concurrency/example/lock/LockExample1.java rename to src/main/java/com/javaedge/concurrency/lock/LockExample1.java index 8cd84b0..04994ee 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/lock/LockExample1.java +++ b/src/main/java/com/javaedge/concurrency/lock/LockExample1.java @@ -1,6 +1,6 @@ -package com.javaedge.concurrency.example.lock; +package main.java.com.javaedge.concurrency.lock; -import com.javaedge.concurrency.annoations.ThreadSafe; +import main.java.com.javaedge.concurrency.annoations.ThreadSafe; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.CountDownLatch; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/lock/LockExample2.java b/src/main/java/com/javaedge/concurrency/lock/LockExample2.java similarity index 93% rename from concurrency/src/main/java/com/javaedge/concurrency/example/lock/LockExample2.java rename to src/main/java/com/javaedge/concurrency/lock/LockExample2.java index ae631bb..af76c79 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/lock/LockExample2.java +++ b/src/main/java/com/javaedge/concurrency/lock/LockExample2.java @@ -1,6 +1,6 @@ -package com.javaedge.concurrency.example.lock; +package main.java.com.javaedge.concurrency.lock; -import com.javaedge.concurrency.annoations.ThreadSafe; +import main.java.com.javaedge.concurrency.annoations.ThreadSafe; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.CountDownLatch; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/lock/LockExample3.java b/src/main/java/com/javaedge/concurrency/lock/LockExample3.java similarity index 95% rename from concurrency/src/main/java/com/javaedge/concurrency/example/lock/LockExample3.java rename to src/main/java/com/javaedge/concurrency/lock/LockExample3.java index d6c0be0..6afe438 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/lock/LockExample3.java +++ b/src/main/java/com/javaedge/concurrency/lock/LockExample3.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.lock; +package main.java.com.javaedge.concurrency.lock; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/lock/LockExample4.java b/src/main/java/com/javaedge/concurrency/lock/LockExample4.java similarity index 97% rename from concurrency/src/main/java/com/javaedge/concurrency/example/lock/LockExample4.java rename to src/main/java/com/javaedge/concurrency/lock/LockExample4.java index b775e55..b43892f 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/lock/LockExample4.java +++ b/src/main/java/com/javaedge/concurrency/lock/LockExample4.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.lock; +package main.java.com.javaedge.concurrency.lock; import java.util.concurrent.locks.StampedLock; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/lock/LockExample5.java b/src/main/java/com/javaedge/concurrency/lock/LockExample5.java similarity index 79% rename from concurrency/src/main/java/com/javaedge/concurrency/example/lock/LockExample5.java rename to src/main/java/com/javaedge/concurrency/lock/LockExample5.java index cbb9e12..201bc89 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/lock/LockExample5.java +++ b/src/main/java/com/javaedge/concurrency/lock/LockExample5.java @@ -1,6 +1,6 @@ -package com.javaedge.concurrency.example.lock; +package main.java.com.javaedge.concurrency.lock; -import com.javaedge.concurrency.annoations.ThreadSafe; +import main.java.com.javaedge.concurrency.annoations.ThreadSafe; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.CountDownLatch; @@ -9,6 +9,9 @@ import java.util.concurrent.Semaphore; import java.util.concurrent.locks.StampedLock; +/** + * @author JavaEdge + */ @Slf4j @ThreadSafe public class LockExample5 { @@ -21,13 +24,13 @@ public class LockExample5 { public static int count = 0; - private final static StampedLock lock = new StampedLock(); + private final static StampedLock STAMPED_LOCK = new StampedLock(); public static void main(String[] args) throws Exception { ExecutorService executorService = Executors.newCachedThreadPool(); final Semaphore semaphore = new Semaphore(threadTotal); final CountDownLatch countDownLatch = new CountDownLatch(clientTotal); - for (int i = 0; i < clientTotal ; i++) { + for (int i = 0; i < clientTotal; i++) { executorService.execute(() -> { try { semaphore.acquire(); @@ -45,11 +48,11 @@ public static void main(String[] args) throws Exception { } private static void add() { - long stamp = lock.writeLock(); + long stamp = STAMPED_LOCK.writeLock(); try { count++; } finally { - lock.unlock(stamp); + STAMPED_LOCK.unlock(stamp); } } } diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/lock/LockExample6.java b/src/main/java/com/javaedge/concurrency/lock/LockExample6.java similarity index 93% rename from concurrency/src/main/java/com/javaedge/concurrency/example/lock/LockExample6.java rename to src/main/java/com/javaedge/concurrency/lock/LockExample6.java index 94fae7b..7afb645 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/lock/LockExample6.java +++ b/src/main/java/com/javaedge/concurrency/lock/LockExample6.java @@ -1,10 +1,13 @@ -package com.javaedge.concurrency.example.lock; +package main.java.com.javaedge.concurrency.lock; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; +/** + * @author JavaEdge + */ @Slf4j public class LockExample6 { diff --git a/src/main/java/com/javaedge/concurrency/lock/LockTest.java b/src/main/java/com/javaedge/concurrency/lock/LockTest.java new file mode 100644 index 0000000..86021b5 --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/lock/LockTest.java @@ -0,0 +1,25 @@ +package main.java.com.javaedge.concurrency.lock; + +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * @author JavaEdge + * @date 2021/4/21 + */ +public class LockTest { + private final Lock reentrantLock = new ReentrantLock(); + int value; + + public void add() { + // 获取锁 + reentrantLock.lock(); + try { + // 若线程 t1 执行 value+=1,那后续线程t2能看到value正确值吗? + value += 1; + } finally { + // 保证锁能释放 + reentrantLock.unlock(); + } + } +} diff --git a/src/main/java/com/javaedge/concurrency/lock/LockTest2.java b/src/main/java/com/javaedge/concurrency/lock/LockTest2.java new file mode 100644 index 0000000..ea86ce5 --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/lock/LockTest2.java @@ -0,0 +1,38 @@ +package main.java.com.javaedge.concurrency.lock; + +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * @author JavaEdge + * @date 2021/4/21 + */ +public class LockTest2 { + private final Lock reentrantLock = new ReentrantLock(); + int value; + + public int get() { + // 2.获取锁 + // 此时,若锁可重入,则t1可再次加锁 + // 若不可重入,则t1此时会被阻塞 + reentrantLock.lock(); + try { + return value; + } finally { + // 保证锁能释放 + reentrantLock.unlock(); + } + } + + public void add() { + // 获取锁 + reentrantLock.lock(); + try { + // 1.线程 t1 此时已经获取到锁 + value = 1 + get(); + } finally { + // 确保释放锁 + reentrantLock.unlock(); + } + } +} diff --git a/src/main/java/com/javaedge/concurrency/lock/Point.java b/src/main/java/com/javaedge/concurrency/lock/Point.java new file mode 100644 index 0000000..6b84f32 --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/lock/Point.java @@ -0,0 +1,42 @@ +package main.java.com.javaedge.concurrency.lock; + +import java.util.concurrent.locks.StampedLock; + +/** + * @author JavaEdge + * @date 2021/4/23 + */ +class Point { + private int x, y; + final StampedLock stampedLock = new StampedLock(); + + /** + * 计算到原点的距离 + */ + public int distanceFromOrigin() { + + // 1.乐观读,是无锁的 + long stamp = stampedLock.tryOptimisticRead(); + + // 2.由于乐观读是无锁的,所以共享变量x、y读入局部变量时,x、y可能被其他线程修改 + int curX = x, curY = y; + + /** + * 3.所以读完后,还要再验证是否存在写操作 + * 判断执行读操作期间,是否存在写操作 + * 若存在,则stampedLock.validate会返回false + */ + if (!stampedLock.validate(stamp)) { + // 升级为悲观读锁 + stamp = stampedLock.readLock(); + try { + curX = x; + curY = y; + } finally { + // 释放悲观读锁 + stampedLock.unlockRead(stamp); + } + } + return (int) Math.sqrt(curX * curX + curY * curY); + } +} diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/lock/TicketLock.java b/src/main/java/com/javaedge/concurrency/lock/TicketLock.java similarity index 93% rename from concurrency/src/main/java/com/javaedge/concurrency/example/lock/TicketLock.java rename to src/main/java/com/javaedge/concurrency/lock/TicketLock.java index 63de487..5d12bb5 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/lock/TicketLock.java +++ b/src/main/java/com/javaedge/concurrency/lock/TicketLock.java @@ -1,3 +1,5 @@ +package main.java.com.javaedge.concurrency.lock; + import java.util.concurrent.atomic.AtomicInteger; public class TicketLock { diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/mq/Message.java b/src/main/java/com/javaedge/concurrency/mq/Message.java similarity index 57% rename from concurrency/src/main/java/com/javaedge/concurrency/example/mq/Message.java rename to src/main/java/com/javaedge/concurrency/mq/Message.java index 9e008a6..f38d170 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/mq/Message.java +++ b/src/main/java/com/javaedge/concurrency/mq/Message.java @@ -1,9 +1,6 @@ -package com.javaedge.concurrency.example.mq; +package main.java.com.javaedge.concurrency.mq; -import lombok.AllArgsConstructor; import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.extern.slf4j.Slf4j; import java.util.Date; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/mq/MqController.java b/src/main/java/com/javaedge/concurrency/mq/MqController.java similarity index 80% rename from concurrency/src/main/java/com/javaedge/concurrency/example/mq/MqController.java rename to src/main/java/com/javaedge/concurrency/mq/MqController.java index 46d8abe..0d53cf4 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/mq/MqController.java +++ b/src/main/java/com/javaedge/concurrency/mq/MqController.java @@ -1,7 +1,7 @@ -package com.javaedge.concurrency.example.mq; +package main.java.com.javaedge.concurrency.mq; -import com.javaedge.concurrency.example.mq.kafka.KafkaSender; -import com.javaedge.concurrency.example.mq.rabbitmq.RabbitMqClient; +import com.javaedge.concurrency.mq.kafka.KafkaSender; +import com.javaedge.concurrency.mq.rabbitmq.RabbitMqClient; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/mq/kafka/KafkaReceiver.java b/src/main/java/com/javaedge/concurrency/mq/kafka/KafkaReceiver.java similarity index 89% rename from concurrency/src/main/java/com/javaedge/concurrency/example/mq/kafka/KafkaReceiver.java rename to src/main/java/com/javaedge/concurrency/mq/kafka/KafkaReceiver.java index 14544cd..bf384b7 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/mq/kafka/KafkaReceiver.java +++ b/src/main/java/com/javaedge/concurrency/mq/kafka/KafkaReceiver.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.mq.kafka; +package main.java.com.javaedge.concurrency.mq.kafka; import lombok.extern.slf4j.Slf4j; import org.apache.kafka.clients.consumer.ConsumerRecord; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/mq/kafka/KafkaSender.java b/src/main/java/com/javaedge/concurrency/mq/kafka/KafkaSender.java similarity index 87% rename from concurrency/src/main/java/com/javaedge/concurrency/example/mq/kafka/KafkaSender.java rename to src/main/java/com/javaedge/concurrency/mq/kafka/KafkaSender.java index 927a7f1..ea6c3c8 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/mq/kafka/KafkaSender.java +++ b/src/main/java/com/javaedge/concurrency/mq/kafka/KafkaSender.java @@ -1,8 +1,8 @@ -package com.javaedge.concurrency.example.mq.kafka; +package main.java.com.javaedge.concurrency.mq.kafka; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.javaedge.concurrency.example.mq.Message; +import main.java.com.javaedge.concurrency.mq.Message; import lombok.extern.slf4j.Slf4j; import org.springframework.kafka.core.KafkaTemplate; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/mq/kafka/TopicConstants.java b/src/main/java/com/javaedge/concurrency/mq/kafka/TopicConstants.java similarity index 73% rename from concurrency/src/main/java/com/javaedge/concurrency/example/mq/kafka/TopicConstants.java rename to src/main/java/com/javaedge/concurrency/mq/kafka/TopicConstants.java index 137fe91..07255d6 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/mq/kafka/TopicConstants.java +++ b/src/main/java/com/javaedge/concurrency/mq/kafka/TopicConstants.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.mq.kafka; +package main.java.com.javaedge.concurrency.mq.kafka; /** * @author JavaEdge diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/mq/rabbitmq/QueueConstants.java b/src/main/java/com/javaedge/concurrency/mq/rabbitmq/QueueConstants.java similarity index 72% rename from concurrency/src/main/java/com/javaedge/concurrency/example/mq/rabbitmq/QueueConstants.java rename to src/main/java/com/javaedge/concurrency/mq/rabbitmq/QueueConstants.java index 4bc59cf..9c43a3a 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/mq/rabbitmq/QueueConstants.java +++ b/src/main/java/com/javaedge/concurrency/mq/rabbitmq/QueueConstants.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.mq.rabbitmq; +package main.java.com.javaedge.concurrency.mq.rabbitmq; /** * @author JavaEdge diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/mq/rabbitmq/RabbitMqClient.java b/src/main/java/com/javaedge/concurrency/mq/rabbitmq/RabbitMqClient.java similarity index 89% rename from concurrency/src/main/java/com/javaedge/concurrency/example/mq/rabbitmq/RabbitMqClient.java rename to src/main/java/com/javaedge/concurrency/mq/rabbitmq/RabbitMqClient.java index b14c6bc..daef199 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/mq/rabbitmq/RabbitMqClient.java +++ b/src/main/java/com/javaedge/concurrency/mq/rabbitmq/RabbitMqClient.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.mq.rabbitmq; +package main.java.com.javaedge.concurrency.mq.rabbitmq; import lombok.extern.slf4j.Slf4j; import org.springframework.amqp.rabbit.core.RabbitTemplate; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/mq/rabbitmq/RabbitMqConfig.java b/src/main/java/com/javaedge/concurrency/mq/rabbitmq/RabbitMqConfig.java similarity index 86% rename from concurrency/src/main/java/com/javaedge/concurrency/example/mq/rabbitmq/RabbitMqConfig.java rename to src/main/java/com/javaedge/concurrency/mq/rabbitmq/RabbitMqConfig.java index e983afc..b239e62 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/mq/rabbitmq/RabbitMqConfig.java +++ b/src/main/java/com/javaedge/concurrency/mq/rabbitmq/RabbitMqConfig.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.mq.rabbitmq; +package main.java.com.javaedge.concurrency.mq.rabbitmq; import org.springframework.amqp.core.Queue; import org.springframework.context.annotation.Bean; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/mq/rabbitmq/RabbitMqServer.java b/src/main/java/com/javaedge/concurrency/mq/rabbitmq/RabbitMqServer.java similarity index 87% rename from concurrency/src/main/java/com/javaedge/concurrency/example/mq/rabbitmq/RabbitMqServer.java rename to src/main/java/com/javaedge/concurrency/mq/rabbitmq/RabbitMqServer.java index 2e90678..aaba62f 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/mq/rabbitmq/RabbitMqServer.java +++ b/src/main/java/com/javaedge/concurrency/mq/rabbitmq/RabbitMqServer.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.mq.rabbitmq; +package main.java.com.javaedge.concurrency.mq.rabbitmq; import lombok.extern.slf4j.Slf4j; import org.springframework.amqp.rabbit.annotation.RabbitListener; diff --git a/src/main/java/com/javaedge/concurrency/order/OrderSpec.java b/src/main/java/com/javaedge/concurrency/order/OrderSpec.java new file mode 100644 index 0000000..e69de29 diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/publish/Escape.java b/src/main/java/com/javaedge/concurrency/publish/Escape.java similarity index 68% rename from concurrency/src/main/java/com/javaedge/concurrency/example/publish/Escape.java rename to src/main/java/com/javaedge/concurrency/publish/Escape.java index 7dec55b..27958cc 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/publish/Escape.java +++ b/src/main/java/com/javaedge/concurrency/publish/Escape.java @@ -1,7 +1,7 @@ -package com.javaedge.concurrency.example.publish; +package main.java.com.javaedge.concurrency.publish; -import com.javaedge.concurrency.annoations.NotRecommend; -import com.javaedge.concurrency.annoations.NotThreadSafe; +import main.java.com.javaedge.concurrency.annoations.NotRecommend; +import main.java.com.javaedge.concurrency.annoations.NotThreadSafe; import lombok.extern.slf4j.Slf4j; @Slf4j diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/publish/UnsafePublish.java b/src/main/java/com/javaedge/concurrency/publish/UnsafePublish.java similarity index 81% rename from concurrency/src/main/java/com/javaedge/concurrency/example/publish/UnsafePublish.java rename to src/main/java/com/javaedge/concurrency/publish/UnsafePublish.java index 6c9522d..25cc4fe 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/publish/UnsafePublish.java +++ b/src/main/java/com/javaedge/concurrency/publish/UnsafePublish.java @@ -1,6 +1,6 @@ -package com.javaedge.concurrency.example.publish; +package main.java.com.javaedge.concurrency.publish; -import com.javaedge.concurrency.annoations.NotThreadSafe; +import main.java.com.javaedge.concurrency.annoations.NotThreadSafe; import lombok.extern.slf4j.Slf4j; import java.util.Arrays; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/singleton/SingletonExample1.java b/src/main/java/com/javaedge/concurrency/singleton/SingletonExample1.java similarity index 79% rename from concurrency/src/main/java/com/javaedge/concurrency/example/singleton/SingletonExample1.java rename to src/main/java/com/javaedge/concurrency/singleton/SingletonExample1.java index c4c3954..0a3de11 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/singleton/SingletonExample1.java +++ b/src/main/java/com/javaedge/concurrency/singleton/SingletonExample1.java @@ -1,6 +1,6 @@ -package com.javaedge.concurrency.example.singleton; +package main.java.com.javaedge.concurrency.singleton; -import com.javaedge.concurrency.annoations.NotThreadSafe; +import main.java.com.javaedge.concurrency.annoations.NotThreadSafe; /** * 懒汉模式 diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/singleton/SingletonExample2.java b/src/main/java/com/javaedge/concurrency/singleton/SingletonExample2.java similarity index 76% rename from concurrency/src/main/java/com/javaedge/concurrency/example/singleton/SingletonExample2.java rename to src/main/java/com/javaedge/concurrency/singleton/SingletonExample2.java index e19499c..79ac587 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/singleton/SingletonExample2.java +++ b/src/main/java/com/javaedge/concurrency/singleton/SingletonExample2.java @@ -1,6 +1,6 @@ -package com.javaedge.concurrency.example.singleton; +package main.java.com.javaedge.concurrency.singleton; -import com.javaedge.concurrency.annoations.ThreadSafe; +import main.java.com.javaedge.concurrency.annoations.ThreadSafe; /** * 饿汉模式 diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/singleton/SingletonExample3.java b/src/main/java/com/javaedge/concurrency/singleton/SingletonExample3.java similarity index 72% rename from concurrency/src/main/java/com/javaedge/concurrency/example/singleton/SingletonExample3.java rename to src/main/java/com/javaedge/concurrency/singleton/SingletonExample3.java index e0ca068..0290a10 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/singleton/SingletonExample3.java +++ b/src/main/java/com/javaedge/concurrency/singleton/SingletonExample3.java @@ -1,7 +1,7 @@ -package com.javaedge.concurrency.example.singleton; +package main.java.com.javaedge.concurrency.singleton; -import com.javaedge.concurrency.annoations.NotRecommend; -import com.javaedge.concurrency.annoations.ThreadSafe; +import main.java.com.javaedge.concurrency.annoations.NotRecommend; +import main.java.com.javaedge.concurrency.annoations.ThreadSafe; /** * 懒汉模式 diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/singleton/SingletonExample4.java b/src/main/java/com/javaedge/concurrency/singleton/SingletonExample4.java similarity index 89% rename from concurrency/src/main/java/com/javaedge/concurrency/example/singleton/SingletonExample4.java rename to src/main/java/com/javaedge/concurrency/singleton/SingletonExample4.java index 611278d..08414f6 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/singleton/SingletonExample4.java +++ b/src/main/java/com/javaedge/concurrency/singleton/SingletonExample4.java @@ -1,6 +1,6 @@ -package com.javaedge.concurrency.example.singleton; +package main.java.com.javaedge.concurrency.singleton; -import com.javaedge.concurrency.annoations.NotThreadSafe; +import main.java.com.javaedge.concurrency.annoations.NotThreadSafe; /** * 懒汉模式 -》 双重同步锁单例模式 diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/singleton/SingletonExample5.java b/src/main/java/com/javaedge/concurrency/singleton/SingletonExample5.java similarity index 88% rename from concurrency/src/main/java/com/javaedge/concurrency/example/singleton/SingletonExample5.java rename to src/main/java/com/javaedge/concurrency/singleton/SingletonExample5.java index f4c6dfd..ac34369 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/singleton/SingletonExample5.java +++ b/src/main/java/com/javaedge/concurrency/singleton/SingletonExample5.java @@ -1,6 +1,6 @@ -package com.javaedge.concurrency.example.singleton; +package main.java.com.javaedge.concurrency.singleton; -import com.javaedge.concurrency.annoations.ThreadSafe; +import main.java.com.javaedge.concurrency.annoations.ThreadSafe; /** * 懒汉模式 -》 双重同步锁单例模式 diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/singleton/SingletonExample6.java b/src/main/java/com/javaedge/concurrency/singleton/SingletonExample6.java similarity index 83% rename from concurrency/src/main/java/com/javaedge/concurrency/example/singleton/SingletonExample6.java rename to src/main/java/com/javaedge/concurrency/singleton/SingletonExample6.java index 8d02e5e..8313698 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/singleton/SingletonExample6.java +++ b/src/main/java/com/javaedge/concurrency/singleton/SingletonExample6.java @@ -1,6 +1,6 @@ -package com.javaedge.concurrency.example.singleton; +package main.java.com.javaedge.concurrency.singleton; -import com.javaedge.concurrency.annoations.ThreadSafe; +import main.java.com.javaedge.concurrency.annoations.ThreadSafe; /** * 饿汉模式 diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/singleton/SingletonExample7.java b/src/main/java/com/javaedge/concurrency/singleton/SingletonExample7.java similarity index 76% rename from concurrency/src/main/java/com/javaedge/concurrency/example/singleton/SingletonExample7.java rename to src/main/java/com/javaedge/concurrency/singleton/SingletonExample7.java index 4475432..ffb6edb 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/singleton/SingletonExample7.java +++ b/src/main/java/com/javaedge/concurrency/singleton/SingletonExample7.java @@ -1,7 +1,7 @@ -package com.javaedge.concurrency.example.singleton; +package main.java.com.javaedge.concurrency.singleton; -import com.javaedge.concurrency.annoations.Recommend; -import com.javaedge.concurrency.annoations.ThreadSafe; +import main.java.com.javaedge.concurrency.annoations.Recommend; +import main.java.com.javaedge.concurrency.annoations.ThreadSafe; /** * 枚举模式:最安全 diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/streams/ParallelPrime.java b/src/main/java/com/javaedge/concurrency/streams/ParallelPrime.java similarity index 95% rename from concurrency/src/main/java/com/javaedge/concurrency/example/streams/ParallelPrime.java rename to src/main/java/com/javaedge/concurrency/streams/ParallelPrime.java index 53d05ab..0b12d29 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/streams/ParallelPrime.java +++ b/src/main/java/com/javaedge/concurrency/streams/ParallelPrime.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.streams; +package main.java.com.javaedge.concurrency.streams; import com.javaedge.concurrency.common.Timer; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/streams/Summing.java b/src/main/java/com/javaedge/concurrency/streams/Summing.java similarity index 96% rename from concurrency/src/main/java/com/javaedge/concurrency/example/streams/Summing.java rename to src/main/java/com/javaedge/concurrency/streams/Summing.java index f0f73ae..dd4b203 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/streams/Summing.java +++ b/src/main/java/com/javaedge/concurrency/streams/Summing.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.streams; +package main.java.com.javaedge.concurrency.streams; import com.javaedge.concurrency.common.Timer; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/sync/ObjectSyncDemo1.java b/src/main/java/com/javaedge/concurrency/sync/ObjectSyncDemo1.java similarity index 95% rename from concurrency/src/main/java/com/javaedge/concurrency/example/sync/ObjectSyncDemo1.java rename to src/main/java/com/javaedge/concurrency/sync/ObjectSyncDemo1.java index 7fea598..ad2aa6d 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/sync/ObjectSyncDemo1.java +++ b/src/main/java/com/javaedge/concurrency/sync/ObjectSyncDemo1.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.sync; +package main.java.com.javaedge.concurrency.sync; /** * 锁 方法(静态/非静态),代码块(对象/类) diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/sync/ObjectSyncDemo2.java b/src/main/java/com/javaedge/concurrency/sync/ObjectSyncDemo2.java similarity index 91% rename from concurrency/src/main/java/com/javaedge/concurrency/example/sync/ObjectSyncDemo2.java rename to src/main/java/com/javaedge/concurrency/sync/ObjectSyncDemo2.java index 4124e65..538bbd8 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/sync/ObjectSyncDemo2.java +++ b/src/main/java/com/javaedge/concurrency/sync/ObjectSyncDemo2.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.sync; +package main.java.com.javaedge.concurrency.sync; // 可重入 public class ObjectSyncDemo2 { diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/sync/ObjectSyncDemo3.java b/src/main/java/com/javaedge/concurrency/sync/ObjectSyncDemo3.java similarity index 91% rename from concurrency/src/main/java/com/javaedge/concurrency/example/sync/ObjectSyncDemo3.java rename to src/main/java/com/javaedge/concurrency/sync/ObjectSyncDemo3.java index f6a25e7..7ddcd91 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/sync/ObjectSyncDemo3.java +++ b/src/main/java/com/javaedge/concurrency/sync/ObjectSyncDemo3.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.sync; +package main.java.com.javaedge.concurrency.sync; // 锁粗化(运行时 jit 编译优化) // jit 编译后的汇编内容, jitwatch可视化工具进行查看 diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/sync/ObjectSyncDemo4.java b/src/main/java/com/javaedge/concurrency/sync/ObjectSyncDemo4.java similarity index 94% rename from concurrency/src/main/java/com/javaedge/concurrency/example/sync/ObjectSyncDemo4.java rename to src/main/java/com/javaedge/concurrency/sync/ObjectSyncDemo4.java index 8cf9d70..82eb858 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/sync/ObjectSyncDemo4.java +++ b/src/main/java/com/javaedge/concurrency/sync/ObjectSyncDemo4.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.sync; +package main.java.com.javaedge.concurrency.sync; // 锁消除(jit) public class ObjectSyncDemo4 { diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/sync/SynchronizedExample1.java b/src/main/java/com/javaedge/concurrency/sync/SynchronizedExample1.java similarity index 95% rename from concurrency/src/main/java/com/javaedge/concurrency/example/sync/SynchronizedExample1.java rename to src/main/java/com/javaedge/concurrency/sync/SynchronizedExample1.java index 9ba8ced..e1fea73 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/sync/SynchronizedExample1.java +++ b/src/main/java/com/javaedge/concurrency/sync/SynchronizedExample1.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.sync; +package main.java.com.javaedge.concurrency.sync; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/sync/SynchronizedExample2.java b/src/main/java/com/javaedge/concurrency/sync/SynchronizedExample2.java similarity index 95% rename from concurrency/src/main/java/com/javaedge/concurrency/example/sync/SynchronizedExample2.java rename to src/main/java/com/javaedge/concurrency/sync/SynchronizedExample2.java index e43490e..936a33c 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/sync/SynchronizedExample2.java +++ b/src/main/java/com/javaedge/concurrency/sync/SynchronizedExample2.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.sync; +package main.java.com.javaedge.concurrency.sync; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/syncContainer/CollectionsExample1.java b/src/main/java/com/javaedge/concurrency/syncContainer/CollectionsExample1.java similarity index 96% rename from concurrency/src/main/java/com/javaedge/concurrency/example/syncContainer/CollectionsExample1.java rename to src/main/java/com/javaedge/concurrency/syncContainer/CollectionsExample1.java index 81acbb9..c118ff9 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/syncContainer/CollectionsExample1.java +++ b/src/main/java/com/javaedge/concurrency/syncContainer/CollectionsExample1.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.syncContainer; +package main.java.com.javaedge.concurrency.syncContainer; import com.google.common.collect.Lists; import com.javaedge.concurrency.annoations.ThreadSafe; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/syncContainer/CollectionsExample2.java b/src/main/java/com/javaedge/concurrency/syncContainer/CollectionsExample2.java similarity index 96% rename from concurrency/src/main/java/com/javaedge/concurrency/example/syncContainer/CollectionsExample2.java rename to src/main/java/com/javaedge/concurrency/syncContainer/CollectionsExample2.java index 951cfbb..a60e053 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/syncContainer/CollectionsExample2.java +++ b/src/main/java/com/javaedge/concurrency/syncContainer/CollectionsExample2.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.syncContainer; +package main.java.com.javaedge.concurrency.syncContainer; import com.google.common.collect.Sets; import com.javaedge.concurrency.annoations.ThreadSafe; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/syncContainer/CollectionsExample3.java b/src/main/java/com/javaedge/concurrency/syncContainer/CollectionsExample3.java similarity index 96% rename from concurrency/src/main/java/com/javaedge/concurrency/example/syncContainer/CollectionsExample3.java rename to src/main/java/com/javaedge/concurrency/syncContainer/CollectionsExample3.java index e4a7bce..32ec833 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/syncContainer/CollectionsExample3.java +++ b/src/main/java/com/javaedge/concurrency/syncContainer/CollectionsExample3.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.syncContainer; +package main.java.com.javaedge.concurrency.syncContainer; import com.javaedge.concurrency.annoations.ThreadSafe; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/syncContainer/HashTableExample.java b/src/main/java/com/javaedge/concurrency/syncContainer/HashTableExample.java similarity index 96% rename from concurrency/src/main/java/com/javaedge/concurrency/example/syncContainer/HashTableExample.java rename to src/main/java/com/javaedge/concurrency/syncContainer/HashTableExample.java index fa11482..9bdcba0 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/syncContainer/HashTableExample.java +++ b/src/main/java/com/javaedge/concurrency/syncContainer/HashTableExample.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.syncContainer; +package main.java.com.javaedge.concurrency.syncContainer; import com.javaedge.concurrency.annoations.ThreadSafe; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/syncContainer/VectorExample1.java b/src/main/java/com/javaedge/concurrency/syncContainer/VectorExample1.java similarity index 96% rename from concurrency/src/main/java/com/javaedge/concurrency/example/syncContainer/VectorExample1.java rename to src/main/java/com/javaedge/concurrency/syncContainer/VectorExample1.java index 9a3251e..90344c9 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/syncContainer/VectorExample1.java +++ b/src/main/java/com/javaedge/concurrency/syncContainer/VectorExample1.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.syncContainer; +package main.java.com.javaedge.concurrency.syncContainer; import com.javaedge.concurrency.annoations.ThreadSafe; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/syncContainer/VectorExample2.java b/src/main/java/com/javaedge/concurrency/syncContainer/VectorExample2.java similarity index 93% rename from concurrency/src/main/java/com/javaedge/concurrency/example/syncContainer/VectorExample2.java rename to src/main/java/com/javaedge/concurrency/syncContainer/VectorExample2.java index 80273bd..0c6742e 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/syncContainer/VectorExample2.java +++ b/src/main/java/com/javaedge/concurrency/syncContainer/VectorExample2.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.syncContainer; +package main.java.com.javaedge.concurrency.syncContainer; import com.javaedge.concurrency.annoations.NotThreadSafe; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/syncContainer/VectorExample3.java b/src/main/java/com/javaedge/concurrency/syncContainer/VectorExample3.java similarity index 94% rename from concurrency/src/main/java/com/javaedge/concurrency/example/syncContainer/VectorExample3.java rename to src/main/java/com/javaedge/concurrency/syncContainer/VectorExample3.java index 427a7ef..f3994c4 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/syncContainer/VectorExample3.java +++ b/src/main/java/com/javaedge/concurrency/syncContainer/VectorExample3.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.syncContainer; +package main.java.com.javaedge.concurrency.syncContainer; import java.util.Iterator; import java.util.Vector; diff --git a/src/main/java/com/javaedge/concurrency/threadLocal/DirtyDataInThreadLocal.java b/src/main/java/com/javaedge/concurrency/threadLocal/DirtyDataInThreadLocal.java new file mode 100644 index 0000000..ea21286 --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/threadLocal/DirtyDataInThreadLocal.java @@ -0,0 +1,35 @@ +package main.java.com.javaedge.concurrency.threadLocal; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * @author JavaEdge + * @date 2022/10/4 + */ +public class DirtyDataInThreadLocal { + + public static ThreadLocal threadLocal = new ThreadLocal<>(); + + public static void main(String[] args) { + ExecutorService threadPool = Executors.newFixedThreadPool(1); + for (int i = 0; i < 2; i++) { + MyThread myThread = new MyThread(); + threadPool.execute(myThread); + } + } + + private static class MyThread extends Thread { + + private static boolean flag = true; + + @Override + public void run() { + if (flag) { + threadLocal.set(this.getName() + ", session info."); + flag = false; + } + System.out.println(this.getName() + " 线程是 " + threadLocal.get()); + } + } +} diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/threadLocal/RequestHolder.java b/src/main/java/com/javaedge/concurrency/threadLocal/RequestHolder.java similarity index 87% rename from concurrency/src/main/java/com/javaedge/concurrency/example/threadLocal/RequestHolder.java rename to src/main/java/com/javaedge/concurrency/threadLocal/RequestHolder.java index 5847b29..7066bda 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/threadLocal/RequestHolder.java +++ b/src/main/java/com/javaedge/concurrency/threadLocal/RequestHolder.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.threadLocal; +package main.java.com.javaedge.concurrency.threadLocal; /** * diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/threadLocal/ThreadLocalController.java b/src/main/java/com/javaedge/concurrency/threadLocal/ThreadLocalController.java similarity index 88% rename from concurrency/src/main/java/com/javaedge/concurrency/example/threadLocal/ThreadLocalController.java rename to src/main/java/com/javaedge/concurrency/threadLocal/ThreadLocalController.java index 031e5f2..7454d3c 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/threadLocal/ThreadLocalController.java +++ b/src/main/java/com/javaedge/concurrency/threadLocal/ThreadLocalController.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.threadLocal; +package main.java.com.javaedge.concurrency.threadLocal; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; diff --git a/src/main/java/com/javaedge/concurrency/threadpermessage/EchoServer.java b/src/main/java/com/javaedge/concurrency/threadpermessage/EchoServer.java new file mode 100644 index 0000000..706a074 --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/threadpermessage/EchoServer.java @@ -0,0 +1,52 @@ +package main.java.com.javaedge.concurrency.threadpermessage; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; + +/** + * 回显从客户端收到的数据 + * + * @author JavaEdge + */ +public final class EchoServer { + + public static void main(String[] args) throws Exception { + final ServerSocketChannel ssc = ServerSocketChannel.open().bind( + new InetSocketAddress(8080)); + // 处理请求 + try { + while (true) { + // 接收请求 + SocketChannel sc = ssc.accept(); + // 每个请求都创建一个线程 + new Thread(() -> { + try { + // 读Socket + ByteBuffer rb = ByteBuffer.allocateDirect(1024); + sc.read(rb); + //模拟处理请求 + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + // 写Socket + ByteBuffer wb = (ByteBuffer) rb.flip(); + sc.write(wb); + // 关闭Socket + sc.close(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }).start(); + } + } finally { + ssc.close(); + } + } +} + diff --git a/src/main/java/com/javaedge/concurrency/threadpool/MyThreadPool.java b/src/main/java/com/javaedge/concurrency/threadpool/MyThreadPool.java new file mode 100644 index 0000000..c691a43 --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/threadpool/MyThreadPool.java @@ -0,0 +1,70 @@ +package main.java.com.javaedge.concurrency.threadpool; + +import com.google.common.collect.Lists; +import lombok.SneakyThrows; + +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +/** + * 简化线程池 + * + * @author JavaEdge + * @date 2021/5/16 + */ +public class MyThreadPool { + + /** + * 利用阻塞队列实现生产者-消费者模式 + */ + BlockingQueue workQueue; + + /** + * 保存内部工作线程 + */ + List threads = Lists.newArrayList(); + + MyThreadPool(int poolSize, BlockingQueue workQueue) { + this.workQueue = workQueue; + // 创建工作线程 + for (int idx = 0; idx < poolSize; idx++) { + WorkerThread work = new WorkerThread(); + work.start(); + threads.add(work); + } + } + + /** + * 提交任务 + */ + void execute(Runnable command) throws InterruptedException { + // 将任务加入到workQueue + workQueue.put(command); + } + + /** + * 工作线程:负责消费任务,并执行任务 + */ + class WorkerThread extends Thread { + + @SneakyThrows + @Override + public void run() { + // 消费workQueue中的任务并执行 + while (true) { + Runnable task = workQueue.take(); + task.run(); + } + } + } + + public static void main(String[] args) throws InterruptedException { + // 创建有界阻塞队列 + BlockingQueue workQueue = new LinkedBlockingQueue<>(2); + // 创建线程池 + MyThreadPool pool = new MyThreadPool(10, workQueue); + // 提交任务 + pool.execute(() -> System.out.println("hello")); + } +} \ No newline at end of file diff --git a/src/main/java/com/javaedge/concurrency/threadpool/ThreadPool2.java b/src/main/java/com/javaedge/concurrency/threadpool/ThreadPool2.java new file mode 100644 index 0000000..b11477c --- /dev/null +++ b/src/main/java/com/javaedge/concurrency/threadpool/ThreadPool2.java @@ -0,0 +1,50 @@ +package main.java.com.javaedge.concurrency.threadpool; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * @author JavaEdge + */ +public class ThreadPool2 { + + public static void main(String[] args) throws InterruptedException { + // P1、P2阶段共用的线程池 + ExecutorService executorService = Executors.newFixedThreadPool(2); + // P1阶段的闭锁 + CountDownLatch p1 = new CountDownLatch(2); + for (int i = 0; i < 2; i++) { + System.out.println("P1"); + //执行P1阶段任务 + executorService.execute(() -> { + // P2阶段的闭锁 + CountDownLatch p2 = new CountDownLatch(2); + // 执行P2阶段子任务 + for (int j = 0; j < 2; j++) { + executorService.execute(() -> { + System.out.println("P2"); + p2.countDown(); + }); + } + + try { + + /** + * 等待P2阶段任务执行完 + * 线程池里所有的线程都在等待P2阶段任务执行完 + * P2阶段任务何时能执行完? + * 永远都无法执行完!因为线程池里的线程都被阻塞了,没有空闲线程执行P2阶段任务。 + */ + p2.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + p1.countDown(); + }); + } + // 等着P1阶段任务执行完 + p1.await(); + System.out.println("end"); + } +} \ No newline at end of file diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/threadpool/ThreadPoolExample1.java b/src/main/java/com/javaedge/concurrency/threadpool/ThreadPoolExample1.java similarity index 90% rename from concurrency/src/main/java/com/javaedge/concurrency/example/threadpool/ThreadPoolExample1.java rename to src/main/java/com/javaedge/concurrency/threadpool/ThreadPoolExample1.java index 20b963e..1417146 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/threadpool/ThreadPoolExample1.java +++ b/src/main/java/com/javaedge/concurrency/threadpool/ThreadPoolExample1.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.threadpool; +package main.java.com.javaedge.concurrency.threadpool; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/threadpool/ThreadPoolExample2.java b/src/main/java/com/javaedge/concurrency/threadpool/ThreadPoolExample2.java similarity index 90% rename from concurrency/src/main/java/com/javaedge/concurrency/example/threadpool/ThreadPoolExample2.java rename to src/main/java/com/javaedge/concurrency/threadpool/ThreadPoolExample2.java index 5191771..9cd3809 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/threadpool/ThreadPoolExample2.java +++ b/src/main/java/com/javaedge/concurrency/threadpool/ThreadPoolExample2.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.threadpool; +package main.java.com.javaedge.concurrency.threadpool; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/threadpool/ThreadPoolExample3.java b/src/main/java/com/javaedge/concurrency/threadpool/ThreadPoolExample3.java similarity index 90% rename from concurrency/src/main/java/com/javaedge/concurrency/example/threadpool/ThreadPoolExample3.java rename to src/main/java/com/javaedge/concurrency/threadpool/ThreadPoolExample3.java index 255d290..7930097 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/threadpool/ThreadPoolExample3.java +++ b/src/main/java/com/javaedge/concurrency/threadpool/ThreadPoolExample3.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.threadpool; +package main.java.com.javaedge.concurrency.threadpool; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/threadpool/ThreadPoolExample4.java b/src/main/java/com/javaedge/concurrency/threadpool/ThreadPoolExample4.java similarity index 94% rename from concurrency/src/main/java/com/javaedge/concurrency/example/threadpool/ThreadPoolExample4.java rename to src/main/java/com/javaedge/concurrency/threadpool/ThreadPoolExample4.java index 869b627..d9fb5e9 100755 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/threadpool/ThreadPoolExample4.java +++ b/src/main/java/com/javaedge/concurrency/threadpool/ThreadPoolExample4.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.threadpool; +package main.java.com.javaedge.concurrency.threadpool; import lombok.extern.slf4j.Slf4j; diff --git a/concurrency/src/main/java/com/javaedge/concurrency/example/threadpool/ThreadPoolExample5.java b/src/main/java/com/javaedge/concurrency/threadpool/ThreadPoolExample5.java similarity index 96% rename from concurrency/src/main/java/com/javaedge/concurrency/example/threadpool/ThreadPoolExample5.java rename to src/main/java/com/javaedge/concurrency/threadpool/ThreadPoolExample5.java index f9d3462..a02ecc4 100644 --- a/concurrency/src/main/java/com/javaedge/concurrency/example/threadpool/ThreadPoolExample5.java +++ b/src/main/java/com/javaedge/concurrency/threadpool/ThreadPoolExample5.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency.example.threadpool; +package main.java.com.javaedge.concurrency.threadpool; import org.testng.annotations.Test; @@ -28,16 +28,13 @@ public void testCommon(ThreadPoolExecutor threadPoolExecutor) throws Exception { // 测试: 提交15个执行时间需要3秒的任务,看超过大小的2个,对应的处理情况 for (int i = 0; i < 15; i++) { int n = i; - threadPoolExecutor.submit(new Runnable() { - @Override - public void run() { - try { - System.out.println("开始执行:" + n); - Thread.sleep(3000L); - System.err.println("执行结束:" + n); - } catch (InterruptedException e) { - e.printStackTrace(); - } + threadPoolExecutor.submit(() -> { + try { + System.out.println("开始执行:" + n); + Thread.sleep(3000L); + System.err.println("执行结束:" + n); + } catch (InterruptedException e) { + e.printStackTrace(); } }); System.out.println("任务提交成功 :" + i); diff --git a/src/main/java/workerthread/v1/Channel.java b/src/main/java/workerthread/v1/Channel.java new file mode 100644 index 0000000..1b2a201 --- /dev/null +++ b/src/main/java/workerthread/v1/Channel.java @@ -0,0 +1,87 @@ +package main.java.workerthread.v1; + +/** + * 传递工作请求及保存工作线程 + * + * @author JavaEdge + */ +public class Channel { + private static final int MAX_REQUEST = 100; + + /** + * 请求的队列 + */ + private final Request[] requestQueue; + + /** + * 下次 putReq 的位置 + */ + private int tail; + + /** + * 下次 takeReq 的位置 + */ + private int head; + + /** + * Req 的数量 + */ + private int count; + + private final WorkerThread[] threadPool; + + public Channel(int threads) { + this.requestQueue = new Request[MAX_REQUEST]; + this.head = 0; + this.tail = 0; + this.count = 0; + + threadPool = new WorkerThread[threads]; + for (int i = 0; i < threadPool.length; i++) { + threadPool[i] = new WorkerThread("Worker-" + i, this); + } + } + + public void startWorkers() { + for (int i = 0; i < threadPool.length; i++) { + threadPool[i].start(); + } + } + + /** + * 将请求放入队列 + * + * @param request + */ + public synchronized void putRequest(Request request) { + while (count >= requestQueue.length) { + try { + wait(); + } catch (InterruptedException e) { + } + } + requestQueue[tail] = request; + tail = (tail + 1) % requestQueue.length; + count++; + notifyAll(); + } + + /** + * 取出队列中的请求 + * + * @return + */ + public synchronized Request takeRequest() { + while (count <= 0) { + try { + wait(); + } catch (InterruptedException e) { + } + } + Request request = requestQueue[head]; + head = (head + 1) % requestQueue.length; + count--; + notifyAll(); + return request; + } +} diff --git a/src/main/java/workerthread/v1/ClientThread.java b/src/main/java/workerthread/v1/ClientThread.java new file mode 100644 index 0000000..0a777eb --- /dev/null +++ b/src/main/java/workerthread/v1/ClientThread.java @@ -0,0 +1,33 @@ +package main.java.workerthread.v1; + +import java.util.Random; + +/** + * 发送工作请求 + * + * @author JavaEdge + */ +public class ClientThread extends Thread { + private final Channel channel; + + private static final Random random = new Random(); + + public ClientThread(String name, Channel channel) { + super(name); + this.channel = channel; + } + + @Override + public void run() { + for (int i = 0; true; i++) { + // 创建请求实例 + Request request = new Request(getName(), i); + channel.putRequest(request); + try { + Thread.sleep(random.nextInt(1000)); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } +} diff --git a/src/main/java/workerthread/v1/Main.java b/src/main/java/workerthread/v1/Main.java new file mode 100644 index 0000000..ddb2b83 --- /dev/null +++ b/src/main/java/workerthread/v1/Main.java @@ -0,0 +1,22 @@ +package main.java.workerthread.v1; + + +/** + * @author JavaEdge + */ +public class Main { + public static void main(String[] args) { + // 工作线程的个数 + Channel channel = new Channel(5); + channel.startWorkers(); + new ClientThread("Alice", channel).start(); + new ClientThread("Bobby", channel).start(); + new ClientThread("Chris", channel).start(); + + try { + Thread.sleep(30000); + } catch (InterruptedException e) { + } + System.exit(0); + } +} diff --git a/src/main/java/workerthread/v1/Request.java b/src/main/java/workerthread/v1/Request.java new file mode 100644 index 0000000..fe85839 --- /dev/null +++ b/src/main/java/workerthread/v1/Request.java @@ -0,0 +1,36 @@ +package main.java.workerthread.v1; + +/** + * 工作请求 + * + * @author JavaEdge + */ +public class Request { + + /** + * 发送请求的委托人的名字 + */ + private final String name; + + /** + * 请求的编号 + */ + private final int number; + + public Request(String name, int number) { + this.name = name; + this.number = number; + } + + /** + * 处理请求 + */ + public void execute() { + System.out.println(Thread.currentThread().getName() + " executes " + this); + } + + @Override + public String toString() { + return "[ Request from " + name + " No." + number + " ]"; + } +} diff --git a/src/main/java/workerthread/v1/WorkerThread.java b/src/main/java/workerthread/v1/WorkerThread.java new file mode 100644 index 0000000..b6fd422 --- /dev/null +++ b/src/main/java/workerthread/v1/WorkerThread.java @@ -0,0 +1,26 @@ +package main.java.workerthread.v1; + +/** + * 工作线程 + * + * @author JavaEdge + */ +public class WorkerThread extends Thread { + + private final Channel channel; + + public WorkerThread(String name, Channel channel) { + super(name); + this.channel = channel; + } + + @Override + public void run() { + while (true) { + // 获得一个 Req 实例 + Request request = channel.takeRequest(); + // 执行之 + request.execute(); + } + } +} diff --git a/src/main/java/workerthread/v2/Channel.java b/src/main/java/workerthread/v2/Channel.java new file mode 100644 index 0000000..e28e807 --- /dev/null +++ b/src/main/java/workerthread/v2/Channel.java @@ -0,0 +1,19 @@ +package main.java.workerthread.v2; + +import workerthread.v1.Request; + +public final class Channel { + public Channel(int threads) { + } + + public void startWorkers() { + } + + public void putRequest(final Request request) { + new Thread() { + public void run() { + request.execute(); + } + }.start(); + } +} diff --git a/concurrency/src/main/main.iml b/src/main/main.iml similarity index 100% rename from concurrency/src/main/main.iml rename to src/main/main.iml diff --git a/concurrency/src/main/resources/application.properties b/src/main/resources/application.properties similarity index 100% rename from concurrency/src/main/resources/application.properties rename to src/main/resources/application.properties diff --git a/concurrency/src/test/java/com/javaedge/concurrency/ConcurrencyApplicationTests.java b/src/test/com/javaedge/concurrency/ConcurrencyApplicationTests.java similarity index 68% rename from concurrency/src/test/java/com/javaedge/concurrency/ConcurrencyApplicationTests.java rename to src/test/com/javaedge/concurrency/ConcurrencyApplicationTests.java index ccd5c26..3928bea 100755 --- a/concurrency/src/test/java/com/javaedge/concurrency/ConcurrencyApplicationTests.java +++ b/src/test/com/javaedge/concurrency/ConcurrencyApplicationTests.java @@ -1,4 +1,4 @@ -package com.javaedge.concurrency; +package test.com.javaedge.concurrency; import org.junit.Test; import org.junit.runner.RunWith; @@ -10,7 +10,10 @@ public class ConcurrencyApplicationTests { @Test - public void contextLoads() { + public void test() { + Thread thread = new Thread(); + thread.start(); + thread.start(); } } diff --git a/concurrency/src/test/test.iml b/src/test/test.iml similarity index 100% rename from concurrency/src/test/test.iml rename to src/test/test.iml