跳转到内容
唯一赫兹
返回

Java 并发

多线程

JMM(Java Memory Model)

JMM 将内存抽象为两个部分:

线程的创建方式

继承 Thread 类

static class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("test");
    }
}
public static void main(String[] args) {
    MyThread t = new MyThread();
    t.start();
}

实现 Runnable 接口

static class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("test Runnable");
    }
}

public static void main(String[] args) {
    Thread t = new Thread(new MyRunnable());
    t.start();
}

实现 Callable 和 FutureTask

static class MyCallable implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        return 1;
    }
}

public static void main(String[] args) {
    FutureTask<Integer> task = new FutureTask<>(new MyCallable());
    Thread t = new Thread(task);
    t.start();
    try {
        Integer result = task.get();
        System.out.println(result);
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
}

使用线程池 Executor

public static void main(String[] args) {
    ExecutorService executor = Executors.newFixedThreadPool(10);
    for (int i = 0; i < 10; ++i) {
        int finalI = i;
        executor.submit(() -> System.out.println(finalI));
    }
    executor.close();
}

interrupt 方法的行为

每个线程内部会维护一个 boolean 值,存储「中断状态」,默认为 false,当在外部调用 interrupt 方法的时候,会修改目标线程的中断状态为 true,并根据情况响应:

线程的状态

sleep()wait() 的区别

BLOCKEDWAITING 的区别

线程池

线程池的使用

ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
    corePoolSize, // 核心线程数 线程池长期维持的最小线程数
    corePoolSize * 2, // 最大线程数 线程池能容纳的最多线程数
    60L, // 空闲线程存活时间 超过核心线程数的空闲线程 多久后销毁
    TimeUnit.SECONDS, // 存活时间单位
    new ArrayBlockingQueue<>(100), // 任务阻塞队列 核心线程忙时 新任务存这里
    Executors.defaultThreadFactory(), // 线程创建工厂 用于设置线程名 优先级等
    new ThreadPoolExecutor.AbortPolicy() // 拒绝策略 队列满且线程数达最大时 如何处理新任务
);

// 提交任务的两种方式和之前一致 这里用execute提交Runnable(无返回值 不能捕获异常)
threadPool.execute(() -> {
    // 函数式接口,如果有返回值就是Callable类,没有就是Runnable类
});

// 关闭线程池 推荐用shutdown 等待已提交任务完成后再关闭
threadPool.shutdown();
// 若需要强制关闭 可调用shutdownNow 会中断正在执行的任务 返回未执行的任务
// List<Runnable> unExecutedTasks = threadPool.shutdownNow();

线程池的工作流程

  1. 判断线程数是否到达核心数,未到达则直接创建新的核心线程,反之将任务加入等待队列
  2. 判断队列是否已满,如果未满则放入,已满则创建非核心线程
  3. 判断线程数是否达到最大线程数,如果未到达则创建非核心线程,反之则根据策略拒绝任务

线程池的参数

public ThreadPoolExecutor(
    int corePoolSize,
    int maximumPoolSize,
    long keepAliveTime,
    TimeUnit unit,
    BlockingQueue<Runnable> workQueue,
    ThreadFactory threadFactory,
    RejectedExecutionHandler handler
)

拒绝策略

线程池的种类



上一篇
Redis 持久化
下一篇
JVM 内存模型