diff --git a/README.md b/README.md index f9e8048..d68ea21 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ > 1、文章会优先更新在Github和公总号里,个人博客可能会有延迟。 > -> 2、如果想要良好的阅读体验,可以[Github在线阅读](https://blog.youthlql.vip/JavaYouth/),或者[Gitee在线阅读](https://youthlql.gitee.io/JavaYouth),[个人博客](https://youthlql.gitee.io/)。Gitee在线阅读和个人博客加载速度比较快。 +> 2、如果Github很卡,可以在[Gitee](https://gitee.com/youthlql/JavaYouth)浏览,或者[Gitee在线阅读](https://youthlql.gitee.io/JavaYouth),[个人博客](https://youthlql.gitee.io/)。Gitee在线阅读和个人博客加载速度比较快。 > > 3、转载须知:转载请注明GitHub出处,让我们一起维护一个良好的技术创作环境! > diff --git a/docs/Java/Basis/Java8_New_Features/Java8新特性.md b/docs/Java/Basis/Java8_New_Features/Java8新特性.md index 9d277da..6fce726 100644 --- a/docs/Java/Basis/Java8_New_Features/Java8新特性.md +++ b/docs/Java/Basis/Java8_New_Features/Java8新特性.md @@ -1,3 +1,22 @@ +--- +title: 详解JDK8新特性 +tags: + - Java8 + - JDK8 + - 新特性 +categories: + - Java + - 新特性 +keywords: Java8,新特性,JDK8 +description: 详解JDK8出现的新特性。 +cover: 'https://cdn.jsdelivr.net/gh/youthlql/lql_img/Java_Basis/javabasis_logo.png' +top_img: 'https://cdn.jsdelivr.net/gh/youthlql/lql_img/blog/top_img.jpg' +abbrlink: de3879ae +date: 2020-10-19 22:15:58 +--- + + + # Java8新特性纵览 > 本篇文章只讲解比较重要的 @@ -1456,7 +1475,7 @@ public class SuperClass { -``` +```java public interface CompareB { default void method3(){ diff --git a/docs/Java/Basis/keyAndDifficultPoints/Generic/泛型.md b/docs/Java/Basis/keyAndDifficultPoints/Generic/泛型.md index 1e6d7d3..5886395 100644 --- a/docs/Java/Basis/keyAndDifficultPoints/Generic/泛型.md +++ b/docs/Java/Basis/keyAndDifficultPoints/Generic/泛型.md @@ -1,3 +1,22 @@ +--- +title: 详解JDK8新特性 +tags: + - Java + - 基础 + - 泛型 +categories: + - Java + - 新特性 +keywords: Java基础,泛型 +description: 万字长文详解Java泛型。 +cover: 'https://cdn.jsdelivr.net/gh/youthlql/lql_img/Java_Basis/javabasis_logo.png' +top_img: 'https://cdn.jsdelivr.net/gh/youthlql/lql_img/blog/top_img.jpg' +abbrlink: de3879ae +date: 2020-10-19 22:21:58 +--- + + + # 简介 ## 泛型的优点 @@ -10,7 +29,7 @@ 那么泛型的好处就是在编译的时候能够检查类型安全,并且所有的强制转换都是自动和隐式的。 -``` +```java public class GlmapperGeneric { private T t; public void set(T t) { this.t = t; } @@ -642,28 +661,30 @@ Process finished with exit code 0 即:**如果静态方法要使用泛型的话,必须将静态方法也定义成泛型方法** 。 - public class StaticGenerator { - - /** - * 1、如果在类中定义使用泛型的静态方法,需要添加额外的泛型声明(将这个方法定义成泛型方法) - * 即使静态方法要使用泛型类中已经声明过的泛型也不可以。 - * 如:public static void show(T t){..},此时编译器会提示错误信息: - "StaticGenerator cannot be refrenced from static context" - * 2、泛型方法:在方法中出现了泛型的结构,泛型参数与类的泛型参数没有任何关系。换句话说, - * 泛型方法所属的类是不是泛型类都没有关系。 - * 3、泛型方法,可以声明为静态的。原因:泛型参数是在调用方法时确定的。并非在初始化类时确定,所以无所谓 - */ - public static List copyFromArrayToList(E[] arr){ - - ArrayList list = new ArrayList<>(); - - for(E e : arr){ - list.add(e); - } - return list; +```java +public class StaticGenerator { + /** + * 1、如果在类中定义使用泛型的静态方法,需要添加额外的泛型声明(将这个方法定义成泛型方法) + * 即使静态方法要使用泛型类中已经声明过的泛型也不可以。 + * 如:public static void show(T t){..},此时编译器会提示错误信息: + "StaticGenerator cannot be refrenced from static context" + * 2、泛型方法:在方法中出现了泛型的结构,泛型参数与类的泛型参数没有任何关系。换句话说, + * 泛型方法所属的类是不是泛型类都没有关系。 + * 3、泛型方法,可以声明为静态的。原因:泛型参数是在调用方法时确定的。并非在初始化类时确定,所以无所谓 + */ + public static List copyFromArrayToList(E[] arr){ + + ArrayList list = new ArrayList<>(); + + for(E e : arr){ + list.add(e); } + return list; + } +} +``` @@ -1565,7 +1586,7 @@ class keyAndDifficultPoints/principle/Test_Generic1 { 如果顺序变一下 -``` +```java class Test_Generic1 ``` @@ -1573,7 +1594,7 @@ class Test_Generic1 T变成了Collection -``` +```java // class version 52.0 (52) // access flags 0x20 // signature Ljava/lang/Object; @@ -1798,7 +1819,7 @@ test4(queue); ​ 在调用泛型方法的时候,可以指定泛型,也可以不指定泛型。在不指定泛型的情况下,泛型变量的类型为 该方法中的几种类型的同一个父类的最小级,直到Object。在指定泛型的时候,该方法中的几种类型必须是该泛型实例类型或者其子类。 -``` +```java class Test { public static void main(String[] args) { //不指定泛型的时候 diff --git a/docs/Java/concurrency/Java并发体系-第一阶段-多线程基础知识.md b/docs/Java/concurrency/Java并发体系-第一阶段-多线程基础知识.md index 58f6c96..48900f6 100644 --- a/docs/Java/concurrency/Java并发体系-第一阶段-多线程基础知识.md +++ b/docs/Java/concurrency/Java并发体系-第一阶段-多线程基础知识.md @@ -7,7 +7,7 @@ tags: categories: - Java并发 keywords: Java并发,原理,源码 -description: Java并发体系-第一阶段-多线程基础知识,后续会陆续出更深入的。 +description: 万字系列长文讲解Java并发-第一阶段-多线程基础知识。 cover: 'https://cdn.jsdelivr.net/gh/youthlql/lql_img/Java_concurrency/logo_1.png' top_img: 'https://cdn.jsdelivr.net/gh/youthlql/lql_img/blog/top_img.jpg' abbrlink: efc79183 @@ -181,7 +181,7 @@ public class ThreadTest1 { ### Runnable接口构造线程源码 -``` +```java /*下面是Thread类的部分源码*/ //1.用Runnable接口创建线程时会进入这个方法 @@ -287,7 +287,7 @@ MyThread t2 = new MyThread(); //这个构造函数会默认调用Super();也就 -``` +```java //代码从上往下顺序执行 public Thread() { init(null, null, "Thread-" + nextThreadNum(), 0); @@ -374,7 +374,7 @@ private void init(ThreadGroup g, Runnable target, String name, ### 最直观的代码描述 -``` +```java class Window extends Thread{ @@ -418,7 +418,7 @@ public class WindowTest { -``` +```java class Window1 implements Runnable{ private int ticket = 100; @@ -645,7 +645,7 @@ public void run() { Java 线程在运行的生命周期中的指定时刻只可能处于下面 6 种不同状态的其中一个状态,这几个状态在Java源码中用枚举来表示。 - + 线程在生命周期中并不是固定处于某一个状态而是随着代码的执行在不同状态之间切换。Java 线程状态变迁如下图所示。 @@ -928,7 +928,7 @@ public static void main(String[] args) { ## join中断测试 -``` +```java Thread main = Thread.currentThread(); Thread t2 = new Thread() { @Override diff --git a/docs/Java/concurrency/Java并发体系-第三阶段-JUC并发包-[1].md b/docs/Java/concurrency/Java并发体系-第三阶段-JUC并发包-[1].md index b67bead..bf2233a 100644 --- a/docs/Java/concurrency/Java并发体系-第三阶段-JUC并发包-[1].md +++ b/docs/Java/concurrency/Java并发体系-第三阶段-JUC并发包-[1].md @@ -1,3 +1,21 @@ +--- +title: 'Java并发体系-第三阶段-JUC并发包-[1]' +tags: + - Java并发 + - 原理 + - 源码 +categories: + - Java并发 +keywords: Java并发,原理,源码 +description: 万字系列长文讲解-Java并发体系-第三阶段-JUC并发包。JUC在高并发编程中使用频率非常高,这里会详细介绍其用法。 +cover: 'https://cdn.jsdelivr.net/gh/youthlql/lql_img/Java_concurrency/logo_1.png' +top_img: 'https://cdn.jsdelivr.net/gh/youthlql/lql_img/blog/top_img.jpg' +abbrlink: 5be45d9e +date: 2020-10-19 22:13:58 +--- + + + # AtomicXXXFieldUpdater > 算是一个小补充 @@ -1080,8 +1098,10 @@ public class Video34 { ### 构造方法 - public Semaphore(int permits) - public Semaphore(int permits , boolean fair) +```java +public Semaphore(int permits) +public Semaphore(int permits , boolean fair) +``` * `permits`:同一时间可以访问资源的线程数目 @@ -1089,16 +1109,18 @@ public class Video34 { ### 重要方法 - public void acquire() throws InterruptedException - public void release() +```java +public void acquire() throws InterruptedException +public void release() +``` * `acquire()`:**获取一个许可证**,如果许可证用完了,则陷入阻塞。可以被打断。 * `release()`:**释放一个许可证** - acquire(int permits) - public void release(int permits) + `acquire(int permits)` + `public void release(int permits)` **acquire多个时,如果没有足够的许可证可用,那么当前线程将被禁用以进行线程调度**,并且处于休眠状态,直到发生两件事情之一: @@ -1107,35 +1129,39 @@ public class Video34 { **release多个时,会使许可证增多,最终可能超过初始值** - public boolean tryAcquire(int permits) - public boolean tryAcquire(int permits, - long timeout, - TimeUnit unit) - throws InterruptedException +```java +public boolean tryAcquire(int permits) +public boolean tryAcquire(int permits, + long timeout, + TimeUnit unit) + throws InterruptedException +``` * 尝试去拿,**拿到返回true** ### 其他方法 - public int availablePermits() +```java +public int availablePermits() +``` * 返回此信号量中当前可用的许可数。 - protected Collection getQueuedThreads() + `protected Collection getQueuedThreads()` public final int getQueueLength() * `getQueuedThreads`返回正在阻塞的线程集合 * `getQueueLength`返回阻塞获取的线程数 - public void acquireUninterruptibly() - public void acquireUninterruptibly(int permits) + `public void acquireUninterruptibly()` + `public void acquireUninterruptibly(int permits)` * 可以`不被打断`获取许可证 - public int drainPermits() + `public int drainPermits()` * 获取当前全部的许可证目标 @@ -1300,7 +1326,7 @@ C 9 ## Condition版生产者消费者 -``` +```java /** * @Author: youthlql-吕 * @Date: 2019/9/26 15:03 diff --git a/docs/Java/concurrency/Java并发体系-第三阶段-JUC并发包-[2].md b/docs/Java/concurrency/Java并发体系-第三阶段-JUC并发包-[2].md index b766305..1595394 100644 --- a/docs/Java/concurrency/Java并发体系-第三阶段-JUC并发包-[2].md +++ b/docs/Java/concurrency/Java并发体系-第三阶段-JUC并发包-[2].md @@ -1,3 +1,21 @@ +--- +title: 'Java并发体系-第三阶段-JUC并发包-[2]' +tags: + - Java并发 + - 原理 + - 源码 +categories: + - Java并发 +keywords: Java并发,原理,源码 +description: 万字系列长文讲解-Java并发体系-第三阶段-JUC并发包。JUC在高并发编程中使用频率非常高,这里会详细介绍其用法。 +cover: 'https://cdn.jsdelivr.net/gh/youthlql/lql_img/Java_concurrency/logo_1.png' +top_img: 'https://cdn.jsdelivr.net/gh/youthlql/lql_img/blog/top_img.jpg' +abbrlink: 70c90e5d +date: 2020-10-19 22:13:58 +--- + + + # Phaser工具 @@ -286,8 +304,10 @@ public class test { ### 注册 - public int register() - public int bulkRegister(int parties) +```java +public int register() +public int bulkRegister(int parties) +``` **register** @@ -300,9 +320,11 @@ public class test { ### 到达 - public int arrive() - public int arriveAndDeregister() - public int arriveAndAwaitAdvance() +```java +public int arrive() +public int arriveAndDeregister() +public int arriveAndAwaitAdvance() +``` **arrive** @@ -319,54 +341,56 @@ public class test { **举例** - public class PhaserTest { - - private static final Random RANDOM = new Random(); - - public static void main(String[] args) throws InterruptedException { - final Phaser phaser = new Phaser(5); - - for (int i = 0; i < 4; i++) { - new ArriveTask(i,phaser).start(); - } - //等待全部任务进行完成 - phaser.arriveAndAwaitAdvance(); - System.out.println("The phase 1 work finish done."); - +```java +public class PhaserTest { + + private static final Random RANDOM = new Random(); + + public static void main(String[] args) throws InterruptedException { + final Phaser phaser = new Phaser(5); + + for (int i = 0; i < 4; i++) { + new ArriveTask(i,phaser).start(); } - - private static class ArriveTask extends Thread{ - private final Phaser phaser; - - private ArriveTask(int no,Phaser phaser) { - super(String.valueOf(no)); - - this.phaser = phaser; - } - - @Override - public void run() { - System.out.println(getName() + " start working. "); - threadSleep(); - System.out.println(getName() + " The phase one is running."); - phaser.arrive(); - - threadSleep(); - System.out.println(getName() + " keep to other thing. "); - - } - } - - private static void threadSleep() { - try { - TimeUnit.SECONDS.sleep(RANDOM.nextInt(5)); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - + //等待全部任务进行完成 + phaser.arriveAndAwaitAdvance(); + System.out.println("The phase 1 work finish done."); + } + private static class ArriveTask extends Thread{ + private final Phaser phaser; + + private ArriveTask(int no,Phaser phaser) { + super(String.valueOf(no)); + + this.phaser = phaser; + } + + @Override + public void run() { + System.out.println(getName() + " start working. "); + threadSleep(); + System.out.println(getName() + " The phase one is running."); + phaser.arrive(); + + threadSleep(); + System.out.println(getName() + " keep to other thing. "); + + } + } + + private static void threadSleep() { + try { + TimeUnit.SECONDS.sleep(RANDOM.nextInt(5)); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + +} +``` + ### onAdvance() 这个方法是 protected 的,所以它不是 phaser 提供的 API,从方法名字上也可以看出,它会在一个 phase 结束的时候被调用。 @@ -387,8 +411,10 @@ protected boolean onAdvance(int phase, int registeredParties) { ### 监控子线程任务 - public int awaitAdvance(int phase) - public int awaitAdvanceInterruptibly(int phase) throws InterruptedException +```java +public int awaitAdvance(int phase) +public int awaitAdvanceInterruptibly(int phase) throws InterruptedException +``` * 相当于起到监控的作用 @@ -397,22 +423,26 @@ protected boolean onAdvance(int phase, int registeredParties) { **举例** - public static void main(String[] args) throws InterruptedException { - final Phaser phaser = new Phaser(4); - - for (int i = 0; i < 4; i++) { - new AwaitAdvance(i,phaser).start(); - } - //等待全部任务进行完成 - phaser.awaitAdvance(phaser.getPhase()); - System.out.println("The phase 1 work finish done."); +```java +public static void main(String[] args) throws InterruptedException { + final Phaser phaser = new Phaser(4); + + for (int i = 0; i < 4; i++) { + new AwaitAdvance(i,phaser).start(); } + //等待全部任务进行完成 + phaser.awaitAdvance(phaser.getPhase()); + System.out.println("The phase 1 work finish done."); +} +``` ### 强制关闭 - public void forceTermination() - public boolean isTerminated() +```java +public void forceTermination() +public boolean isTerminated() +``` * 强制关闭phaser,但是`如果线程陷入阻塞,不会唤醒` @@ -422,7 +452,9 @@ protected boolean onAdvance(int phase, int registeredParties) { ### 获取阶段数 - public final int getPhase() +```java +public final int getPhase() +``` * 返回当前相位数。 最大相位数为Integer.MAX_VALUE @@ -430,22 +462,24 @@ protected boolean onAdvance(int phase, int registeredParties) { **举例** - public class PhaserTest { - public static void main(String[] args) { - final Phaser phaser = new Phaser(1); - System.out.println(phaser.getPhase()); - - phaser.arriveAndAwaitAdvance(); - System.out.println(phaser.getPhase()); - - phaser.arriveAndAwaitAdvance(); - System.out.println(phaser.getPhase()); - - phaser.arriveAndAwaitAdvance(); - System.out.println(phaser.getPhase()); - - } +```java +public class PhaserTest { + public static void main(String[] args) { + final Phaser phaser = new Phaser(1); + System.out.println(phaser.getPhase()); + + phaser.arriveAndAwaitAdvance(); + System.out.println(phaser.getPhase()); + + phaser.arriveAndAwaitAdvance(); + System.out.println(phaser.getPhase()); + + phaser.arriveAndAwaitAdvance(); + System.out.println(phaser.getPhase()); + } +} +``` **结果**: @@ -458,7 +492,9 @@ protected boolean onAdvance(int phase, int registeredParties) { ### 获取注册的数 - public int getRegisteredParties() +```java +public int getRegisteredParties() +``` * 获得注册的线程数,相当于Countdown初始的的计数器 @@ -466,8 +502,10 @@ protected boolean onAdvance(int phase, int registeredParties) { ### 获得到达和未到达的数目 - public int getArrivedParties() - public int getUnarrivedParties() +```java +public int getArrivedParties() +public int getUnarrivedParties() +``` **getArrivedParties** @@ -488,13 +526,15 @@ protected boolean onAdvance(int phase, int registeredParties) { Phaser 内部用一个 `state` 来管理状态变化,随着 parties 的增加,并发问题带来的性能影响会越来越严重。 - /** - * 0-15: unarrived - * 16-31: parties, 所以一个 phaser 实例最大支持 2^16-1=65535 个 parties - * 32-62: phase, 31 位,那么最大值是 Integer.MAX_VALUE,达到最大值后又从 0 开始 - * 63: terminated - */ - private volatile long state; +```java + /** + * 0-15: unarrived + * 16-31: parties, 所以一个 phaser 实例最大支持 2^16-1=65535 个 parties + * 32-62: phase, 31 位,那么最大值是 Integer.MAX_VALUE,达到最大值后又从 0 开始 + * 63: terminated + */ + private volatile long state; +``` > 通常我们在说 0-15 位这种,说的都是从低位开始的 @@ -507,21 +547,23 @@ protected boolean onAdvance(int phase, int registeredParties) { 这里我们不讲源码,用通俗一点的语言表述一下。我们先写段代码构造一棵树: - Phaser root = new Phaser(5); - - Phaser n1 = new Phaser(root, 5); - Phaser n2 = new Phaser(root, 5); - - Phaser m1 = new Phaser(n1, 5); - Phaser m2 = new Phaser(n1, 5); - Phaser m3 = new Phaser(n1, 5); - - Phaser m4 = new Phaser(n2, 5); +```java + Phaser root = new Phaser(5); + + Phaser n1 = new Phaser(root, 5); + Phaser n2 = new Phaser(root, 5); + + Phaser m1 = new Phaser(n1, 5); + Phaser m2 = new Phaser(n1, 5); + Phaser m3 = new Phaser(n1, 5); + + Phaser m4 = new Phaser(n2, 5); +``` 根据上面的代码,我们可以画出下面这个很简单的图: - ![phaser](image/0002.png) + 这棵树上有 7 个 phaser 实例,每个 phaser 实例在构造的时候,都指定了 parties 为 5,但是,对于每个拥有子节点的节点来说,每个子节点都是它的一个 party,我们可以通过 phaser.getRegisteredParties() 得到每个节点的 parties 数量: @@ -535,18 +577,22 @@ protected boolean onAdvance(int phase, int registeredParties) { 在上面代码的基础上,大家可以试一下下面的这个代码: - Phaser m5 = new Phaser(n2); - System.out.println("n2 parties: " + n2.getRegisteredParties()); - m5.register(); - System.out.println("n2 parties: " + n2.getRegisteredParties()); +```java + Phaser m5 = new Phaser(n2); + System.out.println("n2 parties: " + n2.getRegisteredParties()); + m5.register(); + System.out.println("n2 parties: " + n2.getRegisteredParties()); +``` 第一行代码中构造了 m5 实例,但是此时它的 parties == 0,所以对于父节点 n2 来说,它的 parties 依然是 6,所以第二行代码输出 6。第三行代码注册了 m5 的第一个 party,显然,第四行代码会输出 7。 当子节点的 parties 降为 0 的时候,会从父节点中"剥离",我们在上面的基础上,再加两行代码: - m5.arriveAndDeregister(); - System.out.println("n2 parties: " + n2.getRegisteredParties()); +```java + m5.arriveAndDeregister(); + System.out.println("n2 parties: " + n2.getRegisteredParties()); +``` 由于 m5 之前只有一个 parties,所以一次 arriveAndDeregister() 就会使得它的 parties 变为 0,此时第二行代码输出父节点 n2 的 parties 为 6。 @@ -1211,34 +1257,38 @@ public static ExecutorService newWorkStealingPool() { ## newScheduledThreadPool - public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { - return new ScheduledThreadPoolExecutor(corePoolSize); - } +```java +public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { + return new ScheduledThreadPoolExecutor(corePoolSize); +} +``` * 创建的是一个定时的任务,每隔一段时间就会运行一次 **首先可以对比的就是Timer这个类** - public class ExecutorsTest { - - public static void main(String[] args) throws InterruptedException { - Timer timer = new Timer(); - final TimerTask task = new TimerTask() { - @Override - public void run() { - System.out.println("=====" + System.currentTimeMillis()); - try { - TimeUnit.SECONDS.sleep(2); - } catch (InterruptedException e) { - e.printStackTrace(); - } +```java +public class ExecutorsTest { + + public static void main(String[] args) throws InterruptedException { + Timer timer = new Timer(); + final TimerTask task = new TimerTask() { + @Override + public void run() { + System.out.println("=====" + System.currentTimeMillis()); + try { + TimeUnit.SECONDS.sleep(2); + } catch (InterruptedException e) { + e.printStackTrace(); } - }; - //1秒执行一次 - timer.schedule(task,0,1000); - } + } + }; + //1秒执行一次 + timer.schedule(task,0,1000); } +} +``` **结果** @@ -1269,7 +1319,7 @@ public static ExecutorService newWorkStealingPool() { # ExecutorService -``` +```java public class Video53 { public static void main(String[] args) { ExecutorService threadPool = new ThreadPoolExecutor( @@ -1602,7 +1652,7 @@ public class ExecutorCompletionService implements CompletionService { **执行流程:** -![image-20200914182032618](image/0004.png) + @@ -2258,12 +2308,14 @@ public class Test_Accept { ### 组合两个任务,任务完成后做的操作 - public CompletableFuture runAfterBoth(CompletionStage other, - Runnable action) - public CompletableFuture runAfterBothAsync(CompletionStage other, - Runnable action) - public CompletableFuture runAfterBothAsync(CompletionStage other, - Runnable action) +```java +public CompletableFuture runAfterBoth(CompletionStage other, + Runnable action) +public CompletableFuture runAfterBothAsync(CompletionStage other, + Runnable action) +public CompletableFuture runAfterBothAsync(CompletionStage other, + Runnable action) +``` @@ -2317,12 +2369,14 @@ public class Test_runAfterEither { ### 组合两个任务,处理后,返回一个结果 - public CompletableFuture thenCombine(CompletionStage other, - BiFunction fn) - public CompletableFuture thenCombineAsync(CompletionStage other, - BiFunction fn) - public CompletableFuture thenCombineAsync(CompletionStage other, - BiFunction fn,, Executor executor) +```java +public CompletableFuture thenCombine(CompletionStage other, + BiFunction fn) +public CompletableFuture thenCombineAsync(CompletionStage other, + BiFunction fn) +public CompletableFuture thenCombineAsync(CompletionStage other, + BiFunction fn,, Executor executor) +``` ​ @@ -2402,9 +2456,11 @@ Process finished with exit code 0 #### 当执行完成时执行的操作 - public CompletableFuture whenComplete(BiConsumer action) - public CompletableFuture whenCompleteAsync(BiConsumer action) - public CompletableFuture whenCompleteAsync(BiConsumer action, Executor executor) +```java +public CompletableFuture whenComplete(BiConsumer action) +public CompletableFuture whenCompleteAsync(BiConsumer action) +public CompletableFuture whenCompleteAsync(BiConsumer action, Executor executor) +``` **举例** @@ -2459,19 +2515,21 @@ public class Test_whenComplete { public interface BiConsumer { void accept(T t, U u); } - ``` - +``` + + - * T是执行的结果,U是执行时产生的异常 #### 级联操作 - public CompletableFuture thenApply(Function fn) - public CompletableFuture thenApplyAsync(Function fn) - public CompletableFuture thenApplyAsync(Function fn,Executor executor) +```java +public CompletableFuture thenApply(Function fn) +public CompletableFuture thenApplyAsync(Function fn) +public CompletableFuture thenApplyAsync(Function fn,Executor executor) +``` **举例** @@ -2520,29 +2578,33 @@ public interface Function { #### 处理结果的操作 - public CompletableFuture handle(BiFunction fn) - public CompletableFuture handleAsync(BiFunction fn) - public CompletableFuture handleAsync(BiFunction fn,Executor executor) +```java +public CompletableFuture handle(BiFunction fn) +public CompletableFuture handleAsync(BiFunction fn) +public CompletableFuture handleAsync(BiFunction fn,Executor executor) +``` **举例** - public class CompletableFutureTest { - - public static void main(String[] args) throws Exception { - CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> "Hello"); - - CompletableFuture future = completableFuture.handleAsync((s,t) -> { - String aaa = t + " World !"; - System.out.println(aaa); - return aaa.length(); - }); - System.out.println(future.get()); - Thread.currentThread().join(); - } - +```java +public class CompletableFutureTest { + + public static void main(String[] args) throws Exception { + CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> "Hello"); + + CompletableFuture future = completableFuture.handleAsync((s,t) -> { + String aaa = t + " World !"; + System.out.println(aaa); + return aaa.length(); + }); + System.out.println(future.get()); + Thread.currentThread().join(); } +} +``` + **结果**: @@ -2561,28 +2623,32 @@ public interface Function { #### 处理结果 - public CompletableFuture thenAccept(Consumer action) - public CompletableFuture thenAcceptAsync(Consumer action) - public CompletableFuture thenAcceptAsync(Consumer action,Executor executor) +```java +public CompletableFuture thenAccept(Consumer action) +public CompletableFuture thenAcceptAsync(Consumer action) +public CompletableFuture thenAcceptAsync(Consumer action,Executor executor) +``` **举例** - public class CompletableFutureTest { - - public static void main(String[] args) throws Exception { - CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> "Hello"); - - CompletableFuture future = completableFuture.thenAccept(t -> { - String aaa = t + " World !"; - System.out.println(aaa); - }); - System.out.println(future.get()); - Thread.currentThread().join(); - } - +```java +public class CompletableFutureTest { + + public static void main(String[] args) throws Exception { + CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> "Hello"); + + CompletableFuture future = completableFuture.thenAccept(t -> { + String aaa = t + " World !"; + System.out.println(aaa); + }); + System.out.println(future.get()); + Thread.currentThread().join(); } +} +``` + **结果** @@ -2645,8 +2711,9 @@ Process finished with exit code -1 #### 立马获取结果 - public T getNow(T valueIfAbsent) - +```java +public T getNow(T valueIfAbsent) +``` **举例** diff --git a/docs/Java/concurrency/Java并发体系-第二阶段-锁与同步-[1].md b/docs/Java/concurrency/Java并发体系-第二阶段-锁与同步-[1].md index 03d09b7..c23d52a 100644 --- a/docs/Java/concurrency/Java并发体系-第二阶段-锁与同步-[1].md +++ b/docs/Java/concurrency/Java并发体系-第二阶段-锁与同步-[1].md @@ -1,3 +1,22 @@ +--- +title: 'Java并发体系-第二阶段-锁与同步-[1]' +tags: + - Java并发 + - 原理 + - 源码 +categories: + - Java并发 +keywords: Java并发,原理,源码 +description: '万字系列长文讲解-Java并发体系-第二阶段,从C++和硬件方面讲解。' +cover: 'https://cdn.jsdelivr.net/gh/youthlql/lql_img/Java_concurrency/logo_1.png' +top_img: 'https://cdn.jsdelivr.net/gh/youthlql/lql_img/blog/top_img.jpg' +abbrlink: 230c5bb3 +date: 2020-10-19 22:09:58 +--- + + + + > - 本阶段文章讲的略微深入,一些基础性问题不会讲解,如有基础性问题不懂,可自行查看我前面的文章,或者自行学习。 > - 本篇文章比较适合校招和社招的面试,笔者在2020年面试的过程中,也确实被问到了下面的一些问题。 @@ -165,7 +184,7 @@ jcstress是java并发压测工具。https://wiki.openjdk.java.net/display/CodeTo -``` +```java import org.openjdk.jcstress.annotations.*; import org.openjdk.jcstress.infra.results.I_Result; @@ -576,7 +595,7 @@ volatile不保证原子性,只保证可见性和禁止指令重排 -``` +```java private static volatile SingletonDemo instance = null; private SingletonDemo() { diff --git a/docs/Java/concurrency/Java并发体系-第二阶段-锁与同步-[2].md b/docs/Java/concurrency/Java并发体系-第二阶段-锁与同步-[2].md index aba6660..b43fce3 100644 --- a/docs/Java/concurrency/Java并发体系-第二阶段-锁与同步-[2].md +++ b/docs/Java/concurrency/Java并发体系-第二阶段-锁与同步-[2].md @@ -1,3 +1,21 @@ +--- +title: 'Java并发体系-第二阶段-锁与同步-[2]' +tags: + - Java并发 + - 原理 + - 源码 +categories: + - Java并发 +keywords: Java并发,原理,源码 +description: '万字系列长文讲解-Java并发体系-第二阶段,从C++和硬件方面讲解。' +cover: 'https://cdn.jsdelivr.net/gh/youthlql/lql_img/Java_concurrency/logo_1.png' +top_img: 'https://cdn.jsdelivr.net/gh/youthlql/lql_img/blog/top_img.jpg' +abbrlink: '8210870' +date: 2020-10-19 22:10:58 +--- + + + # 可见性设计的硬件 @@ -64,7 +82,7 @@ isRunning = false; => 写volatile变量,就会通过执行一个内存屏障 ​ 内存屏障是被插入两个CPU指令之间的一种指令,用来禁止处理器指令发生重排序(像屏障一样),从而保障有序性的。另外,为了达到屏障的效果,它也会使处理器写入、读取值之前,将写缓冲器的值写入高速缓存,清空无效队列,实现可见性。 - 举例:将写缓冲器数据写入高速缓存,能够避免不同处理器之间不能访问写缓冲器而导致的可见性问题,以及有效地避免了存储转发问题;清空无效队列保证该处理器上高速缓存中不存在旧的副本,进而拿到最新数据 +​ 举例:将写缓冲器数据写入高速缓存,能够避免不同处理器之间不能访问写缓冲器而导致的可见性问题,以及有效地避免了存储转发问题;清空无效队列保证该处理器上高速缓存中不存在旧的副本,进而拿到最新数据 ## 基本内存屏障 diff --git a/docs/Java/concurrency/Java并发体系-第二阶段-锁与同步-[3].md b/docs/Java/concurrency/Java并发体系-第二阶段-锁与同步-[3].md index d8b1fee..83639fe 100644 --- a/docs/Java/concurrency/Java并发体系-第二阶段-锁与同步-[3].md +++ b/docs/Java/concurrency/Java并发体系-第二阶段-锁与同步-[3].md @@ -1,3 +1,21 @@ +--- +title: 'Java并发体系-第二阶段-锁与同步-[3]' +tags: + - Java并发 + - 原理 + - 源码 +categories: + - Java并发 +keywords: Java并发,原理,源码 +description: '万字系列长文讲解-Java并发体系-第二阶段,从C++和硬件方面讲解。' +cover: 'https://cdn.jsdelivr.net/gh/youthlql/lql_img/Java_concurrency/logo_1.png' +top_img: 'https://cdn.jsdelivr.net/gh/youthlql/lql_img/blog/top_img.jpg' +abbrlink: 113a3931 +date: 2020-10-19 22:10:58 +--- + + + # synchronized保证三大特性 **synchronized保证原子性的原理** @@ -75,7 +93,7 @@ synchronized的锁对象中有一个计数器(recursions变量)会记录线 ### synchronized不可中断演示 -``` +```java public class Test { private static Object obj = new Object(); public static void main(String[] args) throws InterruptedException { @@ -243,7 +261,7 @@ public class SyncTest { 使用javap对其进行反汇编,部分信息如下 -``` +```java { public void syncBlock(); descriptor: ()V @@ -407,7 +425,7 @@ Mark Word用于存储对象自身的运行时数据,如哈希码(HashCode) ## 查看Java对象布局的方法 -``` +```java org.openjdk.jol jol-core @@ -544,7 +562,7 @@ case 3:当其他线程进入同步块时,发现已经有偏向的线程了 我们看个demo,在该demo中重复3次获得锁。 -``` +```java synchronized(obj){ synchronized(obj){ synchronized(obj){