From d4ffc60237b43d46c4fe55a2a144e3474665f86f Mon Sep 17 00:00:00 2001 From: wr <191040964@qq.com> Date: Sun, 12 Jan 2020 21:58:55 +0800 Subject: [PATCH] week_05-23 --- week_05/23/1115leetcode.md | 75 ++++++++++++++++++++++++++++++++ week_05/23/Executors.md | 28 ++++++++++++ week_05/23/Thread.md | 22 ++++++++++ week_05/23/ThreadLocal.md | 10 +++++ week_05/23/ThreadPoolExecutor.md | 50 +++++++++++++++++++++ 5 files changed, 185 insertions(+) create mode 100644 week_05/23/1115leetcode.md create mode 100644 week_05/23/Executors.md create mode 100644 week_05/23/Thread.md create mode 100644 week_05/23/ThreadLocal.md create mode 100644 week_05/23/ThreadPoolExecutor.md diff --git a/week_05/23/1115leetcode.md b/week_05/23/1115leetcode.md new file mode 100644 index 0000000..c242de2 --- /dev/null +++ b/week_05/23/1115leetcode.md @@ -0,0 +1,75 @@ +package com.spd.oth; + + +import java.util.concurrent.Semaphore; + +class FooBar{ + private int n; + + public FooBar(int n) { + this.n = n; + } + + Semaphore foo = new Semaphore(1); + Semaphore bar = new Semaphore(0); + + public void foo(Runnable printFoo) throws InterruptedException { + for (int i = 0; i < n; i++) { + foo.acquire(); + printFoo.run(); + bar.release(); + } + } + + public void bar(Runnable printBar) throws InterruptedException { + for (int i = 0; i < n; i++) { + bar.acquire(); + printBar.run(); + foo.release(); + } + } + + public static void main(String[] args) throws InterruptedException { + FooBar fb = new FooBar(3); + bar bar = new bar(); + foo foo = new foo(); + new Thread() { + public void run() { + try { + fb.bar(bar); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }.start(); + + new Thread() { + public void run() { + try { + fb.foo(foo); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }.start(); + + +​ + } + +} + + +class foo extends Thread{ + @Override + public void run() { + System.out.print("foo"); + } +} + +class bar extends Thread{ + @Override + public void run() { + System.out.print("bar"); + } +} \ No newline at end of file diff --git a/week_05/23/Executors.md b/week_05/23/Executors.md new file mode 100644 index 0000000..c000fb2 --- /dev/null +++ b/week_05/23/Executors.md @@ -0,0 +1,28 @@ +总结: + +java中BlockingQueue主要有两种实现,分别是ArrayBlockingQueue和LinkedBlockingQueue。ArrayBlockingQueue是一个用数组实现的有界阻塞队列,必须设置容量。而LinkedBlockingQueue是一个用链表实现的有界阻塞队列,容量可以选择进行设置,不设置的话,将是一个无边界的阻塞队列,最大长度为Integer.MAX_VALUE. + + + +```java +public static ExecutorService newSingleThreadExecutor() { + return new FinalizableDelegatedExecutorService + (new ThreadPoolExecutor(1, 1, + 0L, TimeUnit.MILLISECONDS, + new LinkedBlockingQueue())); + } + +public static ExecutorService newCachedThreadPool() { + return new ThreadPoolExecutor(0, Integer.MAX_VALUE, + 60L, TimeUnit.SECONDS, + new SynchronousQueue()); + } + + +ThreadPoolExecutor(int corePoolSize, + int maximumPoolSize, + long keepAliveTime, + TimeUnit unit, + BlockingQueue workQueue +``` + diff --git a/week_05/23/Thread.md b/week_05/23/Thread.md new file mode 100644 index 0000000..c5659be --- /dev/null +++ b/week_05/23/Thread.md @@ -0,0 +1,22 @@ +**线程的状态** + +- NEW:初始状态,线程被构建,还未调用start()方法; +- RUNNABLE:运行状态,在java多线程模型中,就绪和运行都是运行状态; +- BLOCKED:阻塞状态; +- WAITING:等待状态,比如中断,需要其他的线程来唤醒; +- TIME_WAITING:超时等待,可以在指定的时间内自行返回; +- TERMINATED:终止状态,线程执行完毕。 + + + +```java + +/* + * Java thread status for tools, default indicates thread 'not yet started' + */ +private volatile int threadStatus; +``` + +根据源码注释,该值用于记录线程是否已经被启动。0表示没有启动。默认为0。若判断到threadStatus不等于0,则抛出异常IllegalThreadStateException + +总结:调用start()最终会调用start0() \ No newline at end of file diff --git a/week_05/23/ThreadLocal.md b/week_05/23/ThreadLocal.md new file mode 100644 index 0000000..c4e20ae --- /dev/null +++ b/week_05/23/ThreadLocal.md @@ -0,0 +1,10 @@ +总结: + +ThreadLocal 不是用于解决共享变量的问题的,也不是为了协调线程同步而存在,而是为了方便每个线程处理自己的状态而引入的一个机制。 + +每个Thread内部都有一个ThreadLocal.ThreadLocalMap类型的成员变量,该成员变量用来存储实际的ThreadLocal变量副本。 + +ThreadLocal并不是为线程保存对象的副本,它仅仅只起到一个索引的作用。它的主要木得视为每一个线程隔离一个类的实例,这个实例的作用范围仅限于线程内部。 + + + diff --git a/week_05/23/ThreadPoolExecutor.md b/week_05/23/ThreadPoolExecutor.md new file mode 100644 index 0000000..0980b9f --- /dev/null +++ b/week_05/23/ThreadPoolExecutor.md @@ -0,0 +1,50 @@ +**`ThreadPoolExecutor` 3 个最重要的参数:** + +- **`corePoolSize` :** 核心线程数线程数定义了最小可以同时运行的线程数量。 +- **`maximumPoolSize` :** 当队列中存放的任务达到队列容量的时候,当前可以同时运行的线程数量变为最大线程数。 +- **`workQueue`:** 当新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,信任就会被存放在队列中。 +- execute()方法 + +```java +// 存放线程池的运行状态 (runState) 和线程池内有效线程的数量 (workerCount) + private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); + + private static int workerCountOf(int c) { + return c & CAPACITY; + } + + private final BlockingQueue workQueue; + + public void execute(Runnable command) { + // 如果任务为null,则抛出异常。 + if (command == null) + throw new NullPointerException(); + // ctl 中保存的线程池当前的一些状态信息 + int c = ctl.get(); + + // 下面会涉及到 3 步 操作 + // 1.首先判断当前线程池中之行的任务数量是否小于 corePoolSize + // 如果小于的话,通过addWorker(command, true)新建一个线程,并将任务(command)添加到该线程中;然后,启动该线程从而执行任务。 + if (workerCountOf(c) < corePoolSize) { + if (addWorker(command, true)) + return; + c = ctl.get(); + } + // 2.如果当前之行的任务数量大于等于 corePoolSize 的时候就会走到这里 + // 通过 isRunning 方法判断线程池状态,线程池处于 RUNNING 状态才会被并且队列可以加入任务,该任务才会被加入进去 + if (isRunning(c) && workQueue.offer(command)) { + int recheck = ctl.get(); + // 再次获取线程池状态,如果线程池状态不是 RUNNING 状态就需要从任务队列中移除任务,并尝试判断线程是否全部执行完毕。同时执行拒绝策略。 + if (!isRunning(recheck) && remove(command)) + reject(command); + // 如果当前线程池为空就新创建一个线程并执行。 + else if (workerCountOf(recheck) == 0) + addWorker(null, false); + } + //3. 通过addWorker(command, false)新建一个线程,并将任务(command)添加到该线程中;然后,启动该线程从而执行任务。 + //如果addWorker(command, false)执行失败,则通过reject()执行相应的拒绝策略的内容。 + else if (!addWorker(command, false)) + reject(command); + } +``` + -- Gitee