From cee46509c824eda6137281c2fced3af48e313a68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B6=E5=AD=90?= Date: Tue, 7 Jan 2020 16:04:48 +0800 Subject: [PATCH 01/20] add week_05/09/Thread. --- week_05/09/Thread | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 week_05/09/Thread diff --git a/week_05/09/Thread b/week_05/09/Thread new file mode 100644 index 0000000..e69de29 -- Gitee From d0e6c48a352dbacb7f3d2457ac5027c84b1aca1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B6=E5=AD=90?= Date: Tue, 7 Jan 2020 16:23:14 +0800 Subject: [PATCH 02/20] thread update --- week_05/09/Thread | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/week_05/09/Thread b/week_05/09/Thread index e69de29..af3e9ee 100644 --- a/week_05/09/Thread +++ b/week_05/09/Thread @@ -0,0 +1,45 @@ +Thread + +1、关于线程 + 看见线程,首先会考虑想到线程与进程的区别,线程的基本状态,线程的调度,线程的切换等相关知识点。(如需要复习,自行查阅相关知识点) + +2、java.lang.Thread类 + 1)实现Runnable接口 + 2)属性 +```java + //线程名字 + private volatile char name[]; + //线程优先级(最大值为10,最小值为1,默认值为5) + private int priority; + private Thread threadQ; + private long eetop; + + /* Whether or not to single_step this thread. */ + private boolean single_step; + + /* 表示线程是否是守护线 */ + private boolean daemon = false; + + /* JVM state */ + private boolean stillborn = false; + + /* 执行任务. */ + private Runnable target; + + /* The group of this thread */ + private ThreadGroup group; + + /* The context ClassLoader for this thread */ + private ClassLoader contextClassLoader; + + /* The inherited AccessControlContext of this thread */ + private AccessControlContext inheritedAccessControlContext; + + /* For autonumbering anonymous threads. */ + private static int threadInitNumber; + + 3)常用方法 + +``` + + -- Gitee From acb958bba0ed488fe13eeecdd4a61690ac696365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B6=E5=AD=90?= Date: Tue, 7 Jan 2020 16:29:07 +0800 Subject: [PATCH 03/20] thread-009.md --- week_05/09/thread.md | 50 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 week_05/09/thread.md diff --git a/week_05/09/thread.md b/week_05/09/thread.md new file mode 100644 index 0000000..05010d8 --- /dev/null +++ b/week_05/09/thread.md @@ -0,0 +1,50 @@ +Thread + +1、关于线程 + 看见线程,首先会考虑想到线程与进程的区别,线程的基本状态,线程的调度,线程的切换等相关知识点。(如需要复习,自行查阅相关知识点) + +2、java.lang.Thread类 + + 1)实现Runnable接口 + + 2)属性 + +```java + //线程名字 + private volatile char name[]; + //线程优先级(最大值为10,最小值为1,默认值为5) + private int priority; + private Thread threadQ; + private long eetop; + + /* Whether or not to single_step this thread. */ + private boolean single_step; + + /* 表示线程是否是守护线 */ + private boolean daemon = false; + + /* JVM state */ + private boolean stillborn = false; + + /* 执行任务. */ + private Runnable target; + + /* The group of this thread */ + private ThreadGroup group; + + /* The context ClassLoader for this thread */ + private ClassLoader contextClassLoader; + + /* The inherited AccessControlContext of this thread */ + private AccessControlContext inheritedAccessControlContext; + + /* For autonumbering anonymous threads. */ + private static int threadInitNumber; + + +``` + 3)常用方法 + + + + -- Gitee From bf59acb9ce1819cebeaada1df5166dca37d5feb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B6=E5=AD=90?= Date: Tue, 7 Jan 2020 16:29:15 +0800 Subject: [PATCH 04/20] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20we?= =?UTF-8?q?ek=5F05/09/Thread?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- week_05/09/Thread | 45 --------------------------------------------- 1 file changed, 45 deletions(-) delete mode 100644 week_05/09/Thread diff --git a/week_05/09/Thread b/week_05/09/Thread deleted file mode 100644 index af3e9ee..0000000 --- a/week_05/09/Thread +++ /dev/null @@ -1,45 +0,0 @@ -Thread - -1、关于线程 - 看见线程,首先会考虑想到线程与进程的区别,线程的基本状态,线程的调度,线程的切换等相关知识点。(如需要复习,自行查阅相关知识点) - -2、java.lang.Thread类 - 1)实现Runnable接口 - 2)属性 -```java - //线程名字 - private volatile char name[]; - //线程优先级(最大值为10,最小值为1,默认值为5) - private int priority; - private Thread threadQ; - private long eetop; - - /* Whether or not to single_step this thread. */ - private boolean single_step; - - /* 表示线程是否是守护线 */ - private boolean daemon = false; - - /* JVM state */ - private boolean stillborn = false; - - /* 执行任务. */ - private Runnable target; - - /* The group of this thread */ - private ThreadGroup group; - - /* The context ClassLoader for this thread */ - private ClassLoader contextClassLoader; - - /* The inherited AccessControlContext of this thread */ - private AccessControlContext inheritedAccessControlContext; - - /* For autonumbering anonymous threads. */ - private static int threadInitNumber; - - 3)常用方法 - -``` - - -- Gitee From 1169ba645d823d9369dd64a2e5a3363a0e5e9413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B6=E5=AD=90?= Date: Wed, 8 Jan 2020 09:59:02 +0800 Subject: [PATCH 05/20] update thread --- week_05/09/thread.md | 315 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 314 insertions(+), 1 deletion(-) diff --git a/week_05/09/thread.md b/week_05/09/thread.md index 05010d8..0f4306c 100644 --- a/week_05/09/thread.md +++ b/week_05/09/thread.md @@ -41,9 +41,322 @@ Thread /* For autonumbering anonymous threads. */ private static int threadInitNumber; + /*栈的深度,默认为0,此数字如何被使用完全取决于虚拟机自己;也有一些虚拟机会忽略此变量值.*/ + private long stackSize; + /* + * JVM-private state that persists after native thread termination. + */ + private long nativeParkEventPointer; + + /* + * Thread ID + */ + private long tid; + + /* For generating thread ID */ + private static long threadSeqNumber; + + /* + * 为工具提供的线程状态值,初始化值标识当前线程还未运行 + */ + private volatile int threadStatus = 0; + + /** + * The minimum priority that a thread can have. + */ + public final static int MIN_PRIORITY = 1; + + /** + * The default priority that is assigned to a thread. + */ + public final static int NORM_PRIORITY = 5; + + /** + * The maximum priority that a thread can have. + */ + public final static int MAX_PRIORITY = 10; +``` + + 3)构造器 + +```java + //默认构造器 + public Thread() + //传入Runnable接口实现 + public Thread(Runnable target) + //设置当前线程用户组 + public Thread(ThreadGroup group, Runnable target) + //设置传入线程名 + public Thread(String name) + //设置用户组,传入线程名 + public Thread(ThreadGroup group, String name) + //传入Runnable接口实现,传入线程名 + public Thread(Runnable target, String name) + //设置用户组,传入Runnable接口实现,传入线程名 + public Thread(ThreadGroup group, Runnable target, String name) + //设置用户组,传入Runnable接口实现,传入线程名,设置当前线程栈大小 + public Thread(ThreadGroup group, Runnable target, String name,long stackSize) + + + /** + * 初始化线程 + * + * @param g the Thread group + * @param target the object whose run() method gets called + * @param name the name of the new Thread + * @param stackSize the desired stack size for the new thread, or + * zero to indicate that this parameter is to be ignored. + * @param acc the AccessControlContext to inherit, or + * AccessController.getContext() if null + */ + private void init(ThreadGroup g, Runnable target, String name, + long stackSize, AccessControlContext acc) { + //线程名称不能为空 + if (name == null) { + throw new NullPointerException("name cannot be null"); + } + + Thread parent = currentThread(); + //获得系统的安全管理器 + SecurityManager security = System.getSecurityManager(); + if (g == null) { // 线程的组为空 + + if (security != null) { + // 线程的组为空,从系统安全管理器中获得线 + g = security.getThreadGroup(); + } + + //系统安全管理器为null,则使用当前执行线程的组 + if (g == null) { + g = parent.getThreadGroup(); + } + } + + //检查是否允许当前线程修改线程组的参数 + g.checkAccess(); + + /* + * 是否受限访问 + */ + if (security != null) { + if (isCCLOverridden(getClass())) { + security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); + } + } + + // 将线程组中的容器容量增加1 + g.addUnstarted(); + + this.group = g; + //继承父线程是否为守护线程 + this.daemon = parent.isDaemon(); + //继承父线程的优先级 + this.priority = parent.getPriority(); + this.name = name.toCharArray(); + // 获取类加载器 + if (security == null || isCCLOverridden(parent.getClass())) + this.contextClassLoader = parent.getContextClassLoader(); + else + this.contextClassLoader = parent.contextClassLoader; + this.inheritedAccessControlContext = + acc != null ? acc : AccessController.getContext(); + // 获取执行方法 + this.target = target; + setPriority(priority); + if (parent.inheritableThreadLocals != null) + this.inheritableThreadLocals = + ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); + /*设置栈的深度 */ + this.stackSize = stackSize; + + /*设置线程id*/ + tid = nextThreadID(); + } ``` - 3)常用方法 +3、常用方法 + +1)start(): + 用来启动一个线程,当调用start方法后,系统才会开启一个新的线程来执行用户定义的子任务,在这个过程中,会为相应的线程分配需要的资源 + +```java +/** + * 线程启动方法 + * 此方法的调用会引起当前线程的执行;JVM会调用此线程的run()方法, + */ +public synchronized void start() { + + /** + * 0状态值代表new状态 + */ + if (threadStatus != 0) + // 不是新创建的状态抛出异常 + throw new IllegalThreadStateException(); + + /** + * 向线程组里添加此线程,注意:线程创建的时候只是将线程组中的容器容量增加1 + */ + group.add(this); + + boolean started = false; + try { + // 使线程进入可运行状态(runnable) + start0(); + started = true; + } finally { + try { + if (!started) { + // 启动失败,再线程组中删除改线程 + group.threadStartFailed(this); + } + } catch (Throwable ignore) { + /* do nothing. If start0 threw a Throwable then + it will be passed up(放弃) the call stack */ + } + } + } + +``` + +2)run(): + 不需要用户来调用的,当通过start方法启动一个线程之后,当线程获得了CPU执行时间,便进入run方法体去执行具体的任务。注意,继承Thread类必须重写run方法,在run方法中定义具体要执行的任务。 + +```java + /** + *线程获得CPU执行权限后执行的方法,实际上是调用的Runnable中的run() + */ + @Override + public void run() { + if (target != null) { + target.run(); + } + } +``` + +3)exit(): + 此方法由系统调用,用于在一个线程退出前做一些扫尾工作。 + +```java + +private void exit() { + if (group != null) { + //加锁执行,删除该线程 + group.threadTerminated(this); + group = null; + } + /* GC回收,全部置为null: see bug 4006245 */ + target = null; + /* 加快释放资源*/ + threadLocals = null; + inheritableThreadLocals = null; + inheritedAccessControlContext = null; + blocker = null; + uncaughtExceptionHandler = null; + } + +``` + +4)interrupt(): + 中断;单独调用interrupt方法可以使得处于阻塞状态的线程抛出一个异常,也就说,它可以用来中断一个正处于阻塞状态的线程;另外,通过interrupt方法和isInterrupted()方法来停止正在运行的线程。 + ( 中断当前线程, 一般来说sleep(),join(),wait()在检查到线程的中断状态的时候,会抛出中断异常InteruptedExeption,以及清除线程的中断状态 ) + +```java + public void interrupt() { + if (this != Thread.currentThread()) + checkAccess(); + // 设置阻塞锁 + synchronized (blockerLock) { + Interruptible b = blocker; + if (b != null) { + interrupt0(); // Just to set the interrupt flag + b.interrupt(this); + return; + } + } + interrupt0(); + } +``` + +5)interrupted() + 中断当前线程是否是中断状态,线程的中断状态会被此方法清除, + 也就是如果此方法两次调用都成功,那么在第二次调用的返回结果为false,除非在第一次调用完后和第二次调用前,当前线程被再次中断, +```java + public static boolean interrupted() { + return currentThread().isInterrupted(true); + } + +``` +6)join() /join(long millis)/join(long millis, int nanos) + +```java + //等待线程死亡 + public final void join() throws InterruptedException { + join(0); + } + + //最多等待参数millis时长,当前线程就会死亡,参数为0时则需要继续等待 + public final synchronized void join(long millis)throws InterruptedException { + long base = System.currentTimeMillis(); + long now = 0; + + if (millis < 0) { //等待时长小于0,不合法,抛出异常 + throw new IllegalArgumentException("timeout value is negative"); + } + + if (millis == 0) { //等待时长为0,继续等 + while (isAlive()) { + wait(0); + } + } else { + while (isAlive()) { + long delay = millis - now; + if (delay <= 0) { + break; + } + wait(delay); + now = System.currentTimeMillis() - base; + } + } + } + + //最多等待参数millis毫秒加nanos纳秒时长,当前线程就会死亡,参数为0时则需要继续等待 + public final synchronized void join(long millis, int nanos)throws InterruptedException { + if (millis < 0) { + throw new IllegalArgumentException("timeout value is negative"); + } + + if (nanos < 0 || nanos > 999999) { + throw new IllegalArgumentException( + "nanosecond timeout value out of range"); + } + + if (nanos >= 500000 || (nanos != 0 && millis == 0)) { + millis++; + } + + join(millis); + } + +``` + +7) dumpStack() + +```java + //将当前线程的堆栈跟踪打印到标准错误流,此方法只用于debug + public static void dumpStack() { + new Exception("Stack trace").printStackTrace(); + } + +``` + +4、总结 + + + + + + + -- Gitee From c81605e270ffc7880d3a241d71d14e86098aab0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B6=E5=AD=90?= Date: Wed, 8 Jan 2020 10:04:09 +0800 Subject: [PATCH 06/20] update thread --- week_05/09/thread.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/week_05/09/thread.md b/week_05/09/thread.md index 0f4306c..4a19521 100644 --- a/week_05/09/thread.md +++ b/week_05/09/thread.md @@ -351,6 +351,12 @@ private void exit() { 4、总结 +5、阅读参考链接: + + https://blog.csdn.net/lxx19941220/article/details/92587043 + https://www.cnblogs.com/albertrui/p/8391447.html + + -- Gitee From 20e1fbf5251c4822ee2a5e07047523e09ba1dd5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B6=E5=AD=90?= Date: Wed, 8 Jan 2020 14:53:29 +0800 Subject: [PATCH 07/20] =?UTF-8?q?Leetcode=E4=BA=A4=E6=9B=BF=E6=89=93?= =?UTF-8?q?=E5=8D=B00=E4=B8=8E=E5=A5=87=E5=81=B6=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...16\345\245\207\345\201\266\346\225\260.md" | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 "week_05/09/Leetcode\344\272\244\346\233\277\346\211\223\345\215\2600\344\270\216\345\245\207\345\201\266\346\225\260.md" diff --git "a/week_05/09/Leetcode\344\272\244\346\233\277\346\211\223\345\215\2600\344\270\216\345\245\207\345\201\266\346\225\260.md" "b/week_05/09/Leetcode\344\272\244\346\233\277\346\211\223\345\215\2600\344\270\216\345\245\207\345\201\266\346\225\260.md" new file mode 100644 index 0000000..6c2a3d4 --- /dev/null +++ "b/week_05/09/Leetcode\344\272\244\346\233\277\346\211\223\345\215\2600\344\270\216\345\245\207\345\201\266\346\225\260.md" @@ -0,0 +1,105 @@ +Leetcode交替打印0与奇偶数 + +题目: + + 每个线程都有一个 printNumber 方法来输出一个整数 + 请修改给出的代码以输出整数序列 010203040506... ,其中序列的长度必须为 2n + +```java + +//利用Semaphore控制实现 +public class ZeroEvenOdd { + + private int n; // n*2n的长度 + + private int num = 0 ; + + Semaphore z = new Semaphore(1); + Semaphore e = new Semaphore(0); + Semaphore o = new Semaphore(0); + + + public ZeroEvenOdd(int n) { + this.n = n; + } + + public void zero() throws InterruptedException { //仅打印出来0 + for(int i=0; i { + + try { + z1.even(); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + + }).start(); + + + //线程b 负责打印奇数 + new Thread(() -> { + + try { + z1.odd(); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + + }).start(); + + //线程c 负责打印0 + new Thread(() -> { + + try { + z1.zero(); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + + }).start(); + + } +} + +``` \ No newline at end of file -- Gitee From fd3d7feb87555a9737304b0db520c079df7616f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B6=E5=AD=90?= Date: Thu, 9 Jan 2020 09:23:48 +0800 Subject: [PATCH 08/20] update ThreadLocal --- week_05/09/ThreadLocal.md | 71 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 week_05/09/ThreadLocal.md diff --git a/week_05/09/ThreadLocal.md b/week_05/09/ThreadLocal.md new file mode 100644 index 0000000..d3a89ad --- /dev/null +++ b/week_05/09/ThreadLocal.md @@ -0,0 +1,71 @@ +ThreadLocal + +1、 + ThreadLocal 是 Thread的一个局部变量,保存线程的副本 + + ThreadLocalMap 是 ThreadLocal 的内部类,是用基于线性探测法的散列表实现的。 + 每一个线程对象可以往 Map 中添加多个 ThreadLocal 对象为键的键值对,每个键对应的值唯一。所以通过一个 ThreadLocal 对象设置的值,在每个线程中都是唯一且互相独立的。 + 唯一是因为键的唯一性,独立是因为每个线程都有自己的ThreadLocalMap内部变量,它是归线程所有的。 + +2、内部类 + + ThreadLocalMap() + +3、构造器 + +```java +//默认构造器 +public ThreadLocal() { +} + +``` + +4、set() :当前线程的 ThreadLocalMap 对象添加键值对,键为 ThreadLocal 对象,值为设置的 value 对象 + +```java +public void set(T value) { + Thread t = Thread.currentThread(); + ThreadLocalMap map = getMap(t); + if (map != null) + map.set(this, value); + else + createMap(t, value); +} + +``` + +5、get(): 线程中调用 get 方法时,如果之前用 set 方法为这个 ThreadLocal 键添加过值,那么就返回设置过的值,否则就返回默认初始值 null + +```java +public T get() { + Thread t = Thread.currentThread(); + ThreadLocalMap map = getMap(t); + if (map != null) { + // 已经调用过set或get方法时,对象值已经设置过,就返回上一次的值 + ThreadLocalMap.Entry e = map.getEntry(this); + if (e != null) { + @SuppressWarnings("unchecked") + T result = (T)e.value; + return result; + } + } + // 没有调用过set或get方法时,对象值没有设置过,就自动设置初始值,并返回初始值 + return setInitialValue(); +} + +private T setInitialValue() { + //获得初始值 + T value = initialValue(); + //set方法 + Thread t = Thread.currentThread(); + ThreadLocalMap map = getMap(t); + if (map != null) + map.set(this, value); + else + createMap(t, value); + return value; +} + + + +``` -- Gitee From 8e89b7024461dadd30d1f46fa78aba052b168d6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B6=E5=AD=90?= Date: Thu, 9 Jan 2020 09:40:37 +0800 Subject: [PATCH 09/20] update threadlocal --- week_05/09/ThreadLocal.md | 1 + 1 file changed, 1 insertion(+) diff --git a/week_05/09/ThreadLocal.md b/week_05/09/ThreadLocal.md index d3a89ad..2a23b56 100644 --- a/week_05/09/ThreadLocal.md +++ b/week_05/09/ThreadLocal.md @@ -6,6 +6,7 @@ ThreadLocal ThreadLocalMap 是 ThreadLocal 的内部类,是用基于线性探测法的散列表实现的。 每一个线程对象可以往 Map 中添加多个 ThreadLocal 对象为键的键值对,每个键对应的值唯一。所以通过一个 ThreadLocal 对象设置的值,在每个线程中都是唯一且互相独立的。 唯一是因为键的唯一性,独立是因为每个线程都有自己的ThreadLocalMap内部变量,它是归线程所有的。 + ThreadLocal是线程Thread中属性threadLocals的管理者,也就是说我们对于ThreadLocal的get, set,remove的操作结果都是针对当前线程Thread实例的threadLocals存,取,删除操作。 2、内部类 -- Gitee From 464f320ad8199f23c8d29ba7ae23bbaf0083fc8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B6=E5=AD=90?= Date: Thu, 9 Jan 2020 09:43:11 +0800 Subject: [PATCH 10/20] add week_04/09/DelayQueue. --- week_04/09/DelayQueue | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 week_04/09/DelayQueue diff --git a/week_04/09/DelayQueue b/week_04/09/DelayQueue new file mode 100644 index 0000000..ea9c10d --- /dev/null +++ b/week_04/09/DelayQueue @@ -0,0 +1,13 @@ +1、总结: + DelayQueue是java并发包下的延时阻塞队列,常用于实现定时任务。 + + 内部存储结构使用优先级队列PriorityQueue q = new PriorityQueue(); + + 入队方法,add(E e)/put(E e) /offer(E e, long timeout, TimeUnit unit)/ ,实现均为offer(E e) + 因为DelayQueue是阻塞队列,且优先级队列是无界的,所以入队不会阻塞不会超时; + + 出队方法,poll()/take() + + demo参考 死磕 java集合之DelayQueue源码分析 + +2、学习参考“彤哥读源码”公众号 -- Gitee From f261d9e81d08bfa83bc3d75971ec2f2c7aa520fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B6=E5=AD=90?= Date: Thu, 9 Jan 2020 09:43:39 +0800 Subject: [PATCH 11/20] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20we?= =?UTF-8?q?ek=5F04/DelayQueue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- week_04/DelayQueue | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 week_04/DelayQueue diff --git a/week_04/DelayQueue b/week_04/DelayQueue deleted file mode 100644 index ea9c10d..0000000 --- a/week_04/DelayQueue +++ /dev/null @@ -1,13 +0,0 @@ -1、总结: - DelayQueue是java并发包下的延时阻塞队列,常用于实现定时任务。 - - 内部存储结构使用优先级队列PriorityQueue q = new PriorityQueue(); - - 入队方法,add(E e)/put(E e) /offer(E e, long timeout, TimeUnit unit)/ ,实现均为offer(E e) - 因为DelayQueue是阻塞队列,且优先级队列是无界的,所以入队不会阻塞不会超时; - - 出队方法,poll()/take() - - demo参考 死磕 java集合之DelayQueue源码分析 - -2、学习参考“彤哥读源码”公众号 -- Gitee From 95997591885ddddd617e27185213024e4a69d73d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B6=E5=AD=90?= Date: Thu, 9 Jan 2020 09:44:55 +0800 Subject: [PATCH 12/20] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20we?= =?UTF-8?q?ek=5F04/09/DelayQueue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- week_04/09/DelayQueue | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 week_04/09/DelayQueue diff --git a/week_04/09/DelayQueue b/week_04/09/DelayQueue deleted file mode 100644 index ea9c10d..0000000 --- a/week_04/09/DelayQueue +++ /dev/null @@ -1,13 +0,0 @@ -1、总结: - DelayQueue是java并发包下的延时阻塞队列,常用于实现定时任务。 - - 内部存储结构使用优先级队列PriorityQueue q = new PriorityQueue(); - - 入队方法,add(E e)/put(E e) /offer(E e, long timeout, TimeUnit unit)/ ,实现均为offer(E e) - 因为DelayQueue是阻塞队列,且优先级队列是无界的,所以入队不会阻塞不会超时; - - 出队方法,poll()/take() - - demo参考 死磕 java集合之DelayQueue源码分析 - -2、学习参考“彤哥读源码”公众号 -- Gitee From 218a983d2bb7e31331b0648e947e3e7eccdc9c5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B6=E5=AD=90?= Date: Thu, 9 Jan 2020 10:30:19 +0800 Subject: [PATCH 13/20] =?UTF-8?q?threadlocal=20=E6=B7=BB=E5=8A=A0WeakRefer?= =?UTF-8?q?ence=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- week_05/09/ThreadLocal.md | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/week_05/09/ThreadLocal.md b/week_05/09/ThreadLocal.md index 2a23b56..ffa8aeb 100644 --- a/week_05/09/ThreadLocal.md +++ b/week_05/09/ThreadLocal.md @@ -11,7 +11,30 @@ ThreadLocal 2、内部类 ThreadLocalMap() - + + ps:注意其中特殊的类WeakReference + + ```java + static class Entry extends WeakReference> { + /** The value associated with this ThreadLocal. */ + Object value; + + Entry(ThreadLocal k, Object v) { + super(k); + value = v; + } + } + ``` + 简单介绍下很少使用的这个类WeakReference + +| 类型 | 回收时间 | 应用场景| +| :------------------------------ | ---------- | ---------| +|强引用 |一直存活,除非GC Roots不可达|所有程序的场景,基本对象,自定义对象等| +|弱引用 |只能存活到下一次GC前 |生命周期很短的对象,例如ThreadLocal中的Key。| +|软引用 |内存不足时会被回收 |一般用在对内存非常敏感的资源上,用作缓存的场景比较多,例如:网页缓存、图片缓存 +|虚引用 |随时会被回收, 创建了可能很快就会被回收|可能被JVM团队内部用来跟踪JVM的垃圾回收活动| + + 3、构造器 ```java @@ -70,3 +93,8 @@ private T setInitialValue() { ``` + +6、模拟复现ThreadLocal导致内存泄漏 + + + -- Gitee From 85648a81186e6bad3cbeec19f0f3d53b3db5dd1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B6=E5=AD=90?= Date: Thu, 9 Jan 2020 14:32:01 +0800 Subject: [PATCH 14/20] update threadlocal --- week_05/09/ThreadLocal.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/week_05/09/ThreadLocal.md b/week_05/09/ThreadLocal.md index ffa8aeb..9e8b188 100644 --- a/week_05/09/ThreadLocal.md +++ b/week_05/09/ThreadLocal.md @@ -94,7 +94,12 @@ private T setInitialValue() { ``` -6、模拟复现ThreadLocal导致内存泄漏 +6、模拟复现ThreadLocal导致内存泄漏(内存检察工具没有装好,暂时未提交) + + + +7、学习参考链接: +https://blog.csdn.net/zzg1229059735/article/details/82715741(包含github地址代码) -- Gitee From 61fb98025f5c569d7376efc5a9460ab1076217f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B6=E5=AD=90?= Date: Fri, 10 Jan 2020 10:59:19 +0800 Subject: [PATCH 15/20] update ThreadPoolExecutor --- week_05/09/ThreadPoolExecutor.md | 209 +++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 week_05/09/ThreadPoolExecutor.md diff --git a/week_05/09/ThreadPoolExecutor.md b/week_05/09/ThreadPoolExecutor.md new file mode 100644 index 0000000..9f9aeb8 --- /dev/null +++ b/week_05/09/ThreadPoolExecutor.md @@ -0,0 +1,209 @@ +ThreadPoolExecutor + +1、认识 + +```java +//继承AbstractExecutorService +public class ThreadPoolExecutor extends AbstractExecutorService{} + +//实现ExecutorService接口 +public abstract class AbstractExecutorService implements ExecutorService{} + +//继承Executor +public interface ExecutorService extends Executor {} + + +public interface Executor { + //启动线程 + void execute(Runnable command); +} + +``` + +2、构造器 + + + +```java + +public ThreadPoolExecutor(int corePoolSize, + int maximumPoolSize, + long keepAliveTime, + TimeUnit unit, + BlockingQueue workQueue, + ThreadFactory threadFactory) { + this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, + threadFactory, defaultHandler); +} + +public ThreadPoolExecutor(int corePoolSize, + int maximumPoolSize, + long keepAliveTime, + TimeUnit unit, + BlockingQueue workQueue, + RejectedExecutionHandler handler) { + this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, + Executors.defaultThreadFactory(), handler); +} + + +public ThreadPoolExecutor(int corePoolSize, + int maximumPoolSize, + long keepAliveTime, + TimeUnit unit, + BlockingQueue workQueue, + ThreadFactory threadFactory, + RejectedExecutionHandler handler) { + if (corePoolSize < 0 || + maximumPoolSize <= 0 || + maximumPoolSize < corePoolSize || + keepAliveTime < 0) + throw new IllegalArgumentException(); + if (workQueue == null || threadFactory == null || handler == null) + throw new NullPointerException(); + this.corePoolSize = corePoolSize; + this.maximumPoolSize = maximumPoolSize; + this.workQueue = workQueue; + this.keepAliveTime = unit.toNanos(keepAliveTime); + this.threadFactory = threadFactory; + this.handler = handler; +} + + +``` + +| 序号 | 名称 | 类型 | 含义 | +| :---| --------------| ----------- |----------- | +| 1 | corePoolSize| int |核心线程池大小| +| 2 | maximumPoolSize| int |最大线程池大小| +| 3 | keepAliveTime | long |线程最大空闲时间| +| 4 | unit | TimeUnit|时间单位 | +| 5 | workQueue | BlockingQueue| 线程等待队列| +| 6 | threadFactory | ThreadFactory|线程创建工厂| +| 7 | handler | RejectedExecutionHandler|拒绝策略| + + +3、执行原理execute() + +```java + + public void execute(Runnable command) { + if (command == null) + throw new NullPointerException(); + int c = ctl.get(); + //工作线程 < 核心线程数量 + if (workerCountOf(c) < corePoolSize) { + //创建线程执行任务 + if (addWorker(command, true)) + return; + c = ctl.get(); + } + //运行态,并尝试将任务加入队列 + if (isRunning(c) && workQueue.offer(command)) { + int recheck = ctl.get(); + if (! isRunning(recheck) && remove(command)) + reject(command); + else if (workerCountOf(recheck) == 0) + addWorker(null, false); + } + //使用尝试最大线程运行 + else if (!addWorker(command, false)) + reject(command); //执行拒绝策略 +} + +//接下来看看addWorker(command,boolean)方法, +//先看不同参数值含义: + +addWorker(command, true): 创建核心线程执行任务; +addWorker(command, false):创建非核心线程执行任务; +addWorker(null, false): 创建非核心线程,当前任务为空 + +//继续具体看看该方法的源码分析 + +private boolean addWorker(Runnable firstTask, boolean core) { + // 第一部分:原子操作、自旋、CAS、重读ctl 等结合,直到确定是否可以创建worker, + // 可以则跳出循环继续操作,否则返回false + retry: + for (;;) { + int c = ctl.get(); + int rs = runStateOf(c); + + // Check if queue empty only if necessary. + if (rs >= SHUTDOWN && + ! (rs == SHUTDOWN && + firstTask == null && + ! workQueue.isEmpty())) + return false; + + for (;;) { + int wc = workerCountOf(c); + if (wc >= CAPACITY || + wc >= (core ? corePoolSize : maximumPoolSize)) + return false; + if (compareAndIncrementWorkerCount(c)) + break retry; + c = ctl.get(); // Re-read ctl + if (runStateOf(c) != rs) + continue retry; + // else CAS failed due to workerCount change; retry inner loop + } + } + + // 第二部分:创建worker,这部分使用ReentrantLock锁 + boolean workerStarted = false; //线程启动标志位 + boolean workerAdded = false; //线程是否加入workers 标志位 + Worker w = null; + try { + w = new Worker(firstTask); //创建worker + final Thread t = w.thread; + if (t != null) { + final ReentrantLock mainLock = this.mainLock; + mainLock.lock(); + try { + // Recheck while holding lock. + // Back out on ThreadFactory failure or if + // shut down before lock acquired. + int rs = runStateOf(ctl.get()); + + if (rs < SHUTDOWN || + (rs == SHUTDOWN && firstTask == null)) { + if (t.isAlive()) // precheck that t is startable + throw new IllegalThreadStateException(); + workers.add(w); + int s = workers.size(); + if (s > largestPoolSize) + largestPoolSize = s; + workerAdded = true; + } + } finally { + mainLock.unlock(); + } + if (workerAdded) { + t.start(); //启动线程 + workerStarted = true; + } + } + } finally { + if (! workerStarted) + addWorkerFailed(w); //失败操作 + } + return workerStarted; +} + + +``` + +4、内部类Worker + +```java +//实现了 Runnable 并继承了AbstractQueuedSynchronizer +private final class Worker + extends AbstractQueuedSynchronizer + implements Runnable{ + + +} + +``` + + -- Gitee From 2bc37920c9b1dca11f9e08fa9907c777485a014e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B6=E5=AD=90?= Date: Fri, 10 Jan 2020 11:42:26 +0800 Subject: [PATCH 16/20] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20we?= =?UTF-8?q?ek=5F05/09/ThreadPoolExecutor.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- week_05/09/ThreadPoolExecutor.md | 209 ------------------------------- 1 file changed, 209 deletions(-) delete mode 100644 week_05/09/ThreadPoolExecutor.md diff --git a/week_05/09/ThreadPoolExecutor.md b/week_05/09/ThreadPoolExecutor.md deleted file mode 100644 index 9f9aeb8..0000000 --- a/week_05/09/ThreadPoolExecutor.md +++ /dev/null @@ -1,209 +0,0 @@ -ThreadPoolExecutor - -1、认识 - -```java -//继承AbstractExecutorService -public class ThreadPoolExecutor extends AbstractExecutorService{} - -//实现ExecutorService接口 -public abstract class AbstractExecutorService implements ExecutorService{} - -//继承Executor -public interface ExecutorService extends Executor {} - - -public interface Executor { - //启动线程 - void execute(Runnable command); -} - -``` - -2、构造器 - - - -```java - -public ThreadPoolExecutor(int corePoolSize, - int maximumPoolSize, - long keepAliveTime, - TimeUnit unit, - BlockingQueue workQueue, - ThreadFactory threadFactory) { - this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, - threadFactory, defaultHandler); -} - -public ThreadPoolExecutor(int corePoolSize, - int maximumPoolSize, - long keepAliveTime, - TimeUnit unit, - BlockingQueue workQueue, - RejectedExecutionHandler handler) { - this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, - Executors.defaultThreadFactory(), handler); -} - - -public ThreadPoolExecutor(int corePoolSize, - int maximumPoolSize, - long keepAliveTime, - TimeUnit unit, - BlockingQueue workQueue, - ThreadFactory threadFactory, - RejectedExecutionHandler handler) { - if (corePoolSize < 0 || - maximumPoolSize <= 0 || - maximumPoolSize < corePoolSize || - keepAliveTime < 0) - throw new IllegalArgumentException(); - if (workQueue == null || threadFactory == null || handler == null) - throw new NullPointerException(); - this.corePoolSize = corePoolSize; - this.maximumPoolSize = maximumPoolSize; - this.workQueue = workQueue; - this.keepAliveTime = unit.toNanos(keepAliveTime); - this.threadFactory = threadFactory; - this.handler = handler; -} - - -``` - -| 序号 | 名称 | 类型 | 含义 | -| :---| --------------| ----------- |----------- | -| 1 | corePoolSize| int |核心线程池大小| -| 2 | maximumPoolSize| int |最大线程池大小| -| 3 | keepAliveTime | long |线程最大空闲时间| -| 4 | unit | TimeUnit|时间单位 | -| 5 | workQueue | BlockingQueue| 线程等待队列| -| 6 | threadFactory | ThreadFactory|线程创建工厂| -| 7 | handler | RejectedExecutionHandler|拒绝策略| - - -3、执行原理execute() - -```java - - public void execute(Runnable command) { - if (command == null) - throw new NullPointerException(); - int c = ctl.get(); - //工作线程 < 核心线程数量 - if (workerCountOf(c) < corePoolSize) { - //创建线程执行任务 - if (addWorker(command, true)) - return; - c = ctl.get(); - } - //运行态,并尝试将任务加入队列 - if (isRunning(c) && workQueue.offer(command)) { - int recheck = ctl.get(); - if (! isRunning(recheck) && remove(command)) - reject(command); - else if (workerCountOf(recheck) == 0) - addWorker(null, false); - } - //使用尝试最大线程运行 - else if (!addWorker(command, false)) - reject(command); //执行拒绝策略 -} - -//接下来看看addWorker(command,boolean)方法, -//先看不同参数值含义: - -addWorker(command, true): 创建核心线程执行任务; -addWorker(command, false):创建非核心线程执行任务; -addWorker(null, false): 创建非核心线程,当前任务为空 - -//继续具体看看该方法的源码分析 - -private boolean addWorker(Runnable firstTask, boolean core) { - // 第一部分:原子操作、自旋、CAS、重读ctl 等结合,直到确定是否可以创建worker, - // 可以则跳出循环继续操作,否则返回false - retry: - for (;;) { - int c = ctl.get(); - int rs = runStateOf(c); - - // Check if queue empty only if necessary. - if (rs >= SHUTDOWN && - ! (rs == SHUTDOWN && - firstTask == null && - ! workQueue.isEmpty())) - return false; - - for (;;) { - int wc = workerCountOf(c); - if (wc >= CAPACITY || - wc >= (core ? corePoolSize : maximumPoolSize)) - return false; - if (compareAndIncrementWorkerCount(c)) - break retry; - c = ctl.get(); // Re-read ctl - if (runStateOf(c) != rs) - continue retry; - // else CAS failed due to workerCount change; retry inner loop - } - } - - // 第二部分:创建worker,这部分使用ReentrantLock锁 - boolean workerStarted = false; //线程启动标志位 - boolean workerAdded = false; //线程是否加入workers 标志位 - Worker w = null; - try { - w = new Worker(firstTask); //创建worker - final Thread t = w.thread; - if (t != null) { - final ReentrantLock mainLock = this.mainLock; - mainLock.lock(); - try { - // Recheck while holding lock. - // Back out on ThreadFactory failure or if - // shut down before lock acquired. - int rs = runStateOf(ctl.get()); - - if (rs < SHUTDOWN || - (rs == SHUTDOWN && firstTask == null)) { - if (t.isAlive()) // precheck that t is startable - throw new IllegalThreadStateException(); - workers.add(w); - int s = workers.size(); - if (s > largestPoolSize) - largestPoolSize = s; - workerAdded = true; - } - } finally { - mainLock.unlock(); - } - if (workerAdded) { - t.start(); //启动线程 - workerStarted = true; - } - } - } finally { - if (! workerStarted) - addWorkerFailed(w); //失败操作 - } - return workerStarted; -} - - -``` - -4、内部类Worker - -```java -//实现了 Runnable 并继承了AbstractQueuedSynchronizer -private final class Worker - extends AbstractQueuedSynchronizer - implements Runnable{ - - -} - -``` - - -- Gitee From c1aaab7f3ae121271a3876198339310679e36ea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B6=E5=AD=90?= Date: Fri, 10 Jan 2020 11:43:06 +0800 Subject: [PATCH 17/20] ThreadPoolExecutor --- week_05/09/ThreadPoolExecutor.md | 265 +++++++++++++++++++++++++++++++ 1 file changed, 265 insertions(+) create mode 100644 week_05/09/ThreadPoolExecutor.md diff --git a/week_05/09/ThreadPoolExecutor.md b/week_05/09/ThreadPoolExecutor.md new file mode 100644 index 0000000..4ad5334 --- /dev/null +++ b/week_05/09/ThreadPoolExecutor.md @@ -0,0 +1,265 @@ +ThreadPoolExecutor + +1、认识 + +```java +//继承AbstractExecutorService +public class ThreadPoolExecutor extends AbstractExecutorService{} + +//实现ExecutorService接口 +public abstract class AbstractExecutorService implements ExecutorService{} + +//继承Executor +public interface ExecutorService extends Executor {} + + +public interface Executor { + //启动线程 + void execute(Runnable command); +} + +``` + +2、构造器 + + + +```java + +public ThreadPoolExecutor(int corePoolSize, + int maximumPoolSize, + long keepAliveTime, + TimeUnit unit, + BlockingQueue workQueue, + ThreadFactory threadFactory) { + this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, + threadFactory, defaultHandler); +} + +public ThreadPoolExecutor(int corePoolSize, + int maximumPoolSize, + long keepAliveTime, + TimeUnit unit, + BlockingQueue workQueue, + RejectedExecutionHandler handler) { + this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, + Executors.defaultThreadFactory(), handler); +} + + +public ThreadPoolExecutor(int corePoolSize, + int maximumPoolSize, + long keepAliveTime, + TimeUnit unit, + BlockingQueue workQueue, + ThreadFactory threadFactory, + RejectedExecutionHandler handler) { + if (corePoolSize < 0 || + maximumPoolSize <= 0 || + maximumPoolSize < corePoolSize || + keepAliveTime < 0) + throw new IllegalArgumentException(); + if (workQueue == null || threadFactory == null || handler == null) + throw new NullPointerException(); + this.corePoolSize = corePoolSize; + this.maximumPoolSize = maximumPoolSize; + this.workQueue = workQueue; + this.keepAliveTime = unit.toNanos(keepAliveTime); + this.threadFactory = threadFactory; + this.handler = handler; +} + + +``` + +| 序号 | 名称 | 类型 | 含义 | +| :---| --------------| ----------- |----------- | +| 1 | corePoolSize| int |核心线程池大小| +| 2 | maximumPoolSize| int |最大线程池大小| +| 3 | keepAliveTime | long |线程最大空闲时间| +| 4 | unit | TimeUnit|时间单位 | +| 5 | workQueue | BlockingQueue| 线程等待队列| +| 6 | threadFactory | ThreadFactory|线程创建工厂| +| 7 | handler | RejectedExecutionHandler|拒绝策略| + + +3、执行原理execute() + +```java + + public void execute(Runnable command) { + if (command == null) + throw new NullPointerException(); + int c = ctl.get(); + //工作线程 < 核心线程数量 + if (workerCountOf(c) < corePoolSize) { + //创建线程执行任务 + if (addWorker(command, true)) + return; + c = ctl.get(); + } + //运行态,并尝试将任务加入队列 + if (isRunning(c) && workQueue.offer(command)) { + int recheck = ctl.get(); + if (! isRunning(recheck) && remove(command)) + reject(command); + else if (workerCountOf(recheck) == 0) + addWorker(null, false); + } + //使用尝试最大线程运行 + else if (!addWorker(command, false)) + reject(command); //执行拒绝策略 +} + +//接下来看看addWorker(command,boolean)方法, +//先看不同参数值含义: + +addWorker(command, true): 创建核心线程执行任务; +addWorker(command, false):创建非核心线程执行任务; +addWorker(null, false): 创建非核心线程,当前任务为空 + +//继续具体看看该方法的源码分析 + +private boolean addWorker(Runnable firstTask, boolean core) { + // 第一部分:原子操作、自旋、CAS、重读ctl 等结合,直到确定是否可以创建worker, + // 可以则跳出循环继续操作,否则返回false + retry: + for (;;) { + int c = ctl.get(); + int rs = runStateOf(c); + + // Check if queue empty only if necessary. + if (rs >= SHUTDOWN && + ! (rs == SHUTDOWN && + firstTask == null && + ! workQueue.isEmpty())) + return false; + + for (;;) { + int wc = workerCountOf(c); + if (wc >= CAPACITY || + wc >= (core ? corePoolSize : maximumPoolSize)) + return false; + if (compareAndIncrementWorkerCount(c)) + break retry; + c = ctl.get(); // Re-read ctl + if (runStateOf(c) != rs) + continue retry; + // else CAS failed due to workerCount change; retry inner loop + } + } + + // 第二部分:创建worker,这部分使用ReentrantLock锁 + boolean workerStarted = false; //线程启动标志位 + boolean workerAdded = false; //线程是否加入workers 标志位 + Worker w = null; + try { + w = new Worker(firstTask); //创建worker + final Thread t = w.thread; + if (t != null) { + final ReentrantLock mainLock = this.mainLock; + mainLock.lock(); + try { + // Recheck while holding lock. + // Back out on ThreadFactory failure or if + // shut down before lock acquired. + int rs = runStateOf(ctl.get()); + + if (rs < SHUTDOWN || + (rs == SHUTDOWN && firstTask == null)) { + if (t.isAlive()) // precheck that t is startable + throw new IllegalThreadStateException(); + workers.add(w); + int s = workers.size(); + if (s > largestPoolSize) + largestPoolSize = s; + workerAdded = true; + } + } finally { + mainLock.unlock(); + } + if (workerAdded) { + t.start(); //启动线程 + workerStarted = true; + } + } + } finally { + if (! workerStarted) + addWorkerFailed(w); //失败操作 + } + return workerStarted; +} + + +``` + +4、内部类Worker + +```java +//实现了 Runnable 并继承了AbstractQueuedSynchronizer +private final class Worker + extends AbstractQueuedSynchronizer + implements Runnable{ + + /**每个worker有自己的内部线程,ThreadFactory创建失败时是null */ + final Thread thread; + /**初始化任务,可能是null*/ + Runnable firstTask; + /**每个worker的完成任务数*/ + volatile long completedTasks; + + Worker(Runnable firstTask) { + setState(-1); // 禁止线程在启动前被打断 + this.firstTask = firstTask; + this.thread = getThreadFactory().newThread(this); + } + + /*重要的执行方法 */ + public void run() { + runWorker(this); + } + + //state = 0 代表未锁;state = 1 代表已锁 + protected boolean isHeldExclusively() { + return getState() != 0; + } + + protected boolean tryAcquire(int unused) { + if (compareAndSetState(0, 1)) { + setExclusiveOwnerThread(Thread.currentThread()); + return true; + } + return false; + } + + protected boolean tryRelease(int unused) { + setExclusiveOwnerThread(null); + setState(0); + return true; + } + + public void lock() { acquire(1); } + public boolean tryLock() { return tryAcquire(1); } + public void unlock() { release(1); } + public boolean isLocked() { return isHeldExclusively(); } + // interrupt已启动线程 + void interruptIfStarted() { + Thread t; + // 初始化是 state = -1,不会被interrupt + if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) { + try { + t.interrupt(); + } catch (SecurityException ignore) { + } + } + } + +} + + +``` + + Worker 实现了简单的 非重入互斥锁,互斥容易理解,非重入是为了避免线程池的一些控制方法获得重入锁,比如setCorePoolSize操作。 + 注意 Worker 实现锁的目的与传统锁的意义不太一样。其主要是为了控制线程是否可interrupt,以及其他的监控,如线程是否 active(正在执行任务)。 + + -- Gitee From d6d2b4e43d11dc44685a74ea9646b6310686491a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B6=E5=AD=90?= Date: Fri, 10 Jan 2020 16:13:33 +0800 Subject: [PATCH 18/20] Executors --- week_05/09/Executors.md | 141 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 week_05/09/Executors.md diff --git a/week_05/09/Executors.md b/week_05/09/Executors.md new file mode 100644 index 0000000..0b74a4c --- /dev/null +++ b/week_05/09/Executors.md @@ -0,0 +1,141 @@ +Executors + + +1)预定义线程池 + +```java +//创建固定数量的普通线程池 +public static ExecutorService newFixedThreadPool(int nThreads) { + //通过ThreadPoolExecutor实现类,创建核心线程数及最大线程数都为nThreads的线程池 + //空闲超时时间为0,且由于核心线程数和最大线程数一样,核心线程不会空闲超时后被回收 + //LinkedBlockingQueue为任务队列实现 + return new ThreadPoolExecutor(nThreads, nThreads, + 0L, TimeUnit.MILLISECONDS, + new LinkedBlockingQueue()); +} + +//nThread为线程池中线程的数量,线程创建的工厂类实现类为threadFactory +public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) { + return new ThreadPoolExecutor(nThreads, nThreads, + 0L, TimeUnit.MILLISECONDS, + new LinkedBlockingQueue(), + threadFactory); +} + +``` + +2)创建可任务窃取的线程池 + +```java +//parallelism并行任务数 +public static ExecutorService newWorkStealingPool(int parallelism) { + + //基于ForkJoinPool创建线程池; + //使用默认线程创建工厂类 + //执行任务异常处理类为null + //任务队列模型为FIFO,true为FIFI,false为FILO + return new ForkJoinPool + (parallelism, + ForkJoinPool.defaultForkJoinWorkerThreadFactory, + null, true); +} + +``` + + +3)创建单个普通线程池 + +```java +//创建单个普通线程池 +public static ExecutorService newSingleThreadExecutor() { + //用FinalizableDelegatedExecutorService进行封装,其会在 + //finalize()方法中调用线程池的shutdown()方法,对线程池进行关闭 + return new FinalizableDelegatedExecutorService + (new ThreadPoolExecutor(1, 1, + 0L, TimeUnit.MILLISECONDS, + new LinkedBlockingQueue())); +} + +public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) { + return new FinalizableDelegatedExecutorService + (new ThreadPoolExecutor(1, 1, + 0L, TimeUnit.MILLISECONDS, + new LinkedBlockingQueue(), + threadFactory)); +} + +``` + + +4)创建线程数量不限的普通线程池 + +```java +//创建缓存的线程池,即线程池数量不限 +public static ExecutorService newCachedThreadPool() { + return new ThreadPoolExecutor(0, Integer.MAX_VALUE, + 60L, TimeUnit.SECONDS, + new SynchronousQueue()); +} + + +public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) { + return new ThreadPoolExecutor(0, Integer.MAX_VALUE, + 60L, TimeUnit.SECONDS, + new SynchronousQueue(), + threadFactory); +} + +``` + +5)创建单个基于时间调度的线程池 + +```java +//创建单个基于时间调度的线程池 +public static ScheduledExecutorService newSingleThreadScheduledExecutor() { + + //利用DelegatedScheduledExecutorService对线程池进行包装 + //DelegatedScheduledExecutorService利用门面模式包装了ScheduledExecutorService + //使得用户无法修改ScheduledExecutorService中的一些参数 + return new DelegatedScheduledExecutorService + (new ScheduledThreadPoolExecutor(1)); +} + + +``` + + +6)创建多个基于时间调度的线程池 + +```java +//创建多个基于时间调度的线程池 +//创建固定线程池的可基于时间调度的线程池,corePoolSize为核心线程池测数量 +public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { + return new ScheduledThreadPoolExecutor(corePoolSize); +} + + +public static ScheduledExecutorService newScheduledThreadPool( + int corePoolSize, ThreadFactory threadFactory) { + return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory); +} +``` + + +7)包装配置不可更改的线程池 + +```java +//对ExecutorService类型线程池进行包装,使用户无法对一些参数进行修改 +public static ExecutorService unconfigurableExecutorService(ExecutorService executor) { + if (executor == null) + throw new NullPointerException(); + return new DelegatedExecutorService(executor); +} + +//对ScheduledExecutorService类型线程池进行包装,使用户无法对一些参数进行修改 +public static ScheduledExecutorService unconfigurableScheduledExecutorService(ScheduledExecutorService executor) { + if (executor == null) + throw new NullPointerException(); + return new DelegatedScheduledExecutorService(executor); +} + +``` \ No newline at end of file -- Gitee From 6b15d95f25ebbfe45e003c407e8f5c3de6ba7041 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B6=E5=AD=90?= Date: Sun, 12 Jan 2020 23:19:16 +0800 Subject: [PATCH 19/20] =?UTF-8?q?rename=20week=5F05/09/Leetcode-=E4=BA=A4?= =?UTF-8?q?=E6=9B=BF=E6=89=93=E5=8D=B0foobar.md=20to=20week=5F05/09/Leetco?= =?UTF-8?q?de-=E4=BA=A4=E6=9B=BF=E6=89=93=E5=8D=B0foobar-update.md.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...4\272\244\346\233\277\346\211\223\345\215\260foobar-update.md" | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename "week_05/09/Leetcode-\344\272\244\346\233\277\346\211\223\345\215\260foobar.md" => "week_05/09/Leetcode-\344\272\244\346\233\277\346\211\223\345\215\260foobar-update.md" (100%) diff --git "a/week_05/09/Leetcode-\344\272\244\346\233\277\346\211\223\345\215\260foobar.md" "b/week_05/09/Leetcode-\344\272\244\346\233\277\346\211\223\345\215\260foobar-update.md" similarity index 100% rename from "week_05/09/Leetcode-\344\272\244\346\233\277\346\211\223\345\215\260foobar.md" rename to "week_05/09/Leetcode-\344\272\244\346\233\277\346\211\223\345\215\260foobar-update.md" -- Gitee From 786f4d3b1c1a24bdee483e8000986cf85095be5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B6=E5=AD=90?= Date: Sun, 12 Jan 2020 23:25:17 +0800 Subject: [PATCH 20/20] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20we?= =?UTF-8?q?ek=5F05/09/Leetcode-=E4=BA=A4=E6=9B=BF=E6=89=93=E5=8D=B0foobar-?= =?UTF-8?q?update.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...7\346\211\223\345\215\260foobar-update.md" | 72 ------------------- 1 file changed, 72 deletions(-) delete mode 100644 "week_05/09/Leetcode-\344\272\244\346\233\277\346\211\223\345\215\260foobar-update.md" diff --git "a/week_05/09/Leetcode-\344\272\244\346\233\277\346\211\223\345\215\260foobar-update.md" "b/week_05/09/Leetcode-\344\272\244\346\233\277\346\211\223\345\215\260foobar-update.md" deleted file mode 100644 index c4db1df..0000000 --- "a/week_05/09/Leetcode-\344\272\244\346\233\277\346\211\223\345\215\260foobar-update.md" +++ /dev/null @@ -1,72 +0,0 @@ -Leetcode——交替打印foobar - -解法一:利用synchronized - -```java -public class FooBar { - - private int n ; //输出次数 - private boolean isFooBar = true; //是否执行打印 - private Object o = new Object(); //锁对象 - - public FooBar(int n) { - this.n = n; - } - - public void foo(Runnable foo) throws InterruptedException { - for(int i = 0; i < n ; i ++){ - synchronized (o){ - if(!isFooBar){ - o.wait(); - } - foo.run(); - isFooBar = false; - System.out.println("foo"); - o.notify(); - } - - } - } - - public void bar(Runnable bar) throws InterruptedException { - for(int j = 0 ; j < n ;j++){ - synchronized (o){ - if(isFooBar){ - o.wait(); - } - bar.run(); - isFooBar = true; - System.out.println("bar"); - o.notify(); - } - - } - } - public static void main(String[] args) throws InterruptedException { - FooBar fooBar = new FooBar(2); - //创建一个foo线程: - new Thread(){ - public void run(){ - try { - fooBar.foo(new Thread()); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - }.start(); - //创建一个bar线程 - new Thread(){ - public void run(){ - try { - fooBar.bar(new Thread()); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - }.start(); - - } -} - -``` - -- Gitee