cheatsheet

151 阅读3分钟

ref:

多进程 vs 多线程

  • 多线程优势:创建线程开销小、通信快(读写同一个变量)
  • 多进程优势:稳定,一个进程崩溃不会影响其他进程,一个线程崩溃会导致整个进程崩溃

一个java程序就是一个JVM进程,这个进程会用一个主线程执行 main()方法,在main()方法内部,可以自定义启动多个线程,此外 JVM 进程还启动着负责 GC 等工作的线程。所以说,java 支持多线程很自然,Java 的多任务一般是指多线程实现多任务。多线程是最基本的并发模型,在读写网络、数据库、web开发等都很常用。

Thread 和 Runnable

java 1 开始就有 Thread 可以用来实现异步,但仅仅依赖这个类来写大型并发比较困难

Runnable task = () -> {
    String threadName = Thread.currentThread().getName();
    System.out.println("Hello " + threadName);
};  // 等号右边也可以直接卸载new Thread()里面。

task.run(); // 在主 thread 中执行

Thread t = new Thread(task);  // 实例化一个线程
t.start(); // 启动线程,新线程会执行run()方法
// t.join(); // 如果有这一句,则主线程会等 t 执行结束再执行,t.join();就是给等待时间加个上限
System.out.println("Done!");  // 这里还是主 thread,它和新起的 thread 不见得谁先谁后结束

java 线程的状态有以下几种:

  • New:新创建的线程,尚未执行;
  • Runnable:运行中的线程,正在执行run()方法的Java代码;
  • Blocked:运行中的线程,因为某些操作被阻塞而挂起;
  • Waiting:运行中的线程,因为某些操作在等待中;
  • Timed Waiting:运行中的线程,因为执行sleep()方法正在计时等待;
  • Terminated:线程已终止,因为run()方法执行完毕。

用一个状态转移图表示如下:

         ┌─────────────┐
         │     New     │
         └─────────────┘
                │
                ▼
┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐
 ┌─────────────┐ ┌─────────────┐
││  Runnable   │ │   Blocked   ││
 └─────────────┘ └─────────────┘
│┌─────────────┐ ┌─────────────┐│
 │   Waiting   │ │Timed Waiting│
│└─────────────┘ └─────────────┘│
 ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
                │
                ▼
         ┌─────────────┐
         │ Terminated  │
         └─────────────┘

Executor Services 和 Future

并发API在2004年Java5发布的时候才被引入。这些API位于java.util.concurrent包下。

java.util.concurrent包包含了很多处理并发编程的类,这些类自推出后就在后续java版本中不断增强。Java8 还提供了新的类和方法。

并发API中最重要的一部分是 executor services

ExecutorService.submit()方法,可以看到,它返回了一个Future类型,一个Future类型的实例代表一个未来能获取结果的对象。

CompletableFuture

廖雪峰 java 8 引入,对 Future 做了改进,可以传入回调对象,当异步任务完成或者发生异常时,自动调用回调对象的回调方法。而不用像 Future那样调用 get()去阻塞地获取结果。

  • Future.get() 就是阻塞调用,在线程获取结果之前get方法会一直阻塞
  • Future提供了一个isDone方法,可以在程序中轮询这个方法查询执行结果。

阻塞的方式和异步编程的设计理念相违背,而轮询的方式会耗费无谓的CPU资源。因此,JDK8设计出CompletableFuture。CompletableFuture提供了一种观察者模式类似的机制,可以让任务执行完成后通知监听的一方。

写法上,CompletableFuture 可以不主动创建线程池(写 ExecutorService)。

  • xxx():表示该方法将继续在已有的线程中执行;
  • xxxAsync():表示将异步在线程池中执行

CompletableFuture可以指定异步处理流程:

  • thenAccept()处理正常结果;
  • exceptional()处理异常结果;
  • thenApplyAsync()用于串行化另一个CompletableFuture
  • anyOf()allOf()用于并行化多个CompletableFuture