From fb9dbb7074c581a235f00749541f095f789373cf Mon Sep 17 00:00:00 2001 From: Omooo <869759698@qq.com> Date: Mon, 18 Mar 2019 21:30:40 +0800 Subject: [PATCH] add Thread/ThreadPool --- .../{Java 并发编程.md => 管程(Monitor).md} | 12 +- blogs/Java/并发/线程、线程池.md | 129 ++++++++++++++++++ 2 files changed, 136 insertions(+), 5 deletions(-) rename blogs/Java/并发/{Java 并发编程.md => 管程(Monitor).md} (96%) create mode 100644 blogs/Java/并发/线程、线程池.md diff --git a/blogs/Java/并发/Java 并发编程.md b/blogs/Java/并发/管程(Monitor).md similarity index 96% rename from blogs/Java/并发/Java 并发编程.md rename to blogs/Java/并发/管程(Monitor).md index 4851461..c75452f 100644 --- a/blogs/Java/并发/Java 并发编程.md +++ b/blogs/Java/并发/管程(Monitor).md @@ -1,10 +1,8 @@ --- -Java 并发编程 +管程:并发编程的万能钥匙 --- -#### 目录 - -#### 管程:并发编程的万能钥匙 +##### 前言 管程,对应的英文是 Monitor,也称监视器。 @@ -68,4 +66,8 @@ Java 参考了 MESA 模型,语言内置的管程(synchronized)对 MESA 模 ![](https://i.loli.net/2019/03/18/5c8f0eba877b4.png) -Java 内置的管程方案(synchronized)使用简单,synchronized 关键字修饰的代码块,在编译期会自动生成相关加锁和解锁的代码,但是仅支持一个条件变量;而 Java SDK 并发包实现的管程支持多个条件变量,不过并发包里的锁,需要开发人员自己进行加锁和解锁操作。 \ No newline at end of file +Java 内置的管程方案(synchronized)使用简单,synchronized 关键字修饰的代码块,在编译期会自动生成相关加锁和解锁的代码,但是仅支持一个条件变量;而 Java SDK 并发包实现的管程支持多个条件变量,不过并发包里的锁,需要开发人员自己进行加锁和解锁操作。 + +##### 摘自: + +[管程:并发编程的万能钥匙](https://time.geekbang.org/column/article/86089) \ No newline at end of file diff --git a/blogs/Java/并发/线程、线程池.md b/blogs/Java/并发/线程、线程池.md new file mode 100644 index 0000000..c938463 --- /dev/null +++ b/blogs/Java/并发/线程、线程池.md @@ -0,0 +1,129 @@ +--- +Java 线程、线程池 +--- + +#### 目录 + +1. 前言 +2. 线程的创建 +3. Callable 与 Future +4. 线程池 +5. 参考 + +#### 前言 + + + +#### 线程的创建 + +我们知道,线程的创建有两种方式:一种是继承 Thread 类,另一种是实现 Runnable 接口。但是这两种方式有一个共同的缺陷,那就是在执行任务后无法获取执行结果(两者 run 方法的返回类型都是 void )。于是在 JDK 5 就引入了 Callable 和 Future。 + +#### Callable 与 Future + +##### Callable + +```java +public interface Callable { + V call() throws Exception; +} +``` + +Callable 是一个泛型接口,你可以完全把它理解为一个有返回类型并且可抛异常的 Runnable。 + +那么是如何获取 Callable 的返回结果呢?通常是通过 FutureTask 这个中间媒介来实现的。 + +##### FutureTask + +FutureTask 实现了 Runnable 和 Future 接口,所以我们可以直接用 Thread 来执行它,也可以使用 ExecuteService 来执行。这里就以 Thread 包装来执行: + +```java +public class ThreadDemo { + public static void main(String[] args) throws Exception { + Callable call = () -> { + System.out.println("线程执行..."); + Thread.sleep(2000); + return 1; + }; + FutureTask task = new FutureTask<>(call); + new Thread(task).start(); + System.out.println(task.get()); + } +} +``` + +##### Future + +Future 的核心思想是:一个方法,计算过程可能非常耗时,等待方法返回显然不可取。可以在执行方法的时候,立马就返回一个 Future 对象,通过这个 Future 对象去控制方法的计算过程。 + +```java +public interface Future { + + /** + * 取消任务 + */ + boolean cancel(boolean mayInterruptIfRunning); + + /** + * 判断是否取消 + */ + boolean isCancelled(); + + /** + * 判断是否已完成 + */ + boolean isDone(); + + /** + * 获取任务结果,如果未完成,则等待 + */ + V get() throws InterruptedException, ExecutionException; + + V get(long timeout, TimeUnit unit) + throws InterruptedException, ExecutionException, TimeoutException; +} +``` + +#### 线程池 + +线程池是为了线程的复用,避免重复创建和销毁线程所带来的性能损耗。 + +##### ThreadPoolExecutor + +ThreadPoolExecutor 类是线程池中最核心的一个类,它提供了四个构造方法: + +```java +public ThreadPoolExecutor(int corePoolSize, + int maximumPoolSize, + long keepAliveTime, + TimeUnit unit, + BlockingQueue workQueue){}; +public ThreadPoolExecutor(int corePoolSize, + int maximumPoolSize, + long keepAliveTime, + TimeUnit unit, + BlockingQueue workQueue, + ThreadFactory threadFactory){}; +public ThreadPoolExecutor(int corePoolSize, + int maximumPoolSize, + long keepAliveTime, + TimeUnit unit, + BlockingQueue workQueue, + RejectedExecutionHandler handler){}; +public ThreadPoolExecutor(int corePoolSize, + int maximumPoolSize, + long keepAliveTime, + TimeUnit unit, + BlockingQueue workQueue, + ThreadFactory threadFactory, + RejectedExecutionHandler handler){}; +``` + +前面三个构造方法都是通过调用第四个构造方法来进行初始化工作的,下面解释一下各个参数的含义: + +- corePoolSize + + 核心线程的大小。在创建线程池后,默认情况下,线程池中并没有任何线程,而是等待有任务到来才创建线程去执行任务,除非调用了 prestartAllCoreThreads() 或者 prestartCoreThread() 方法,从这两个方法名就可以看出,是预创建线程的意思。 + +#### 参考 + +[Java并发编程:线程池的使用](https://www.cnblogs.com/dolphin0520/p/3932921.html) \ No newline at end of file