# 自动创建线程池

## FixedThreadPool

创建一个固定线程数量的线程池, 内部使用无界队列 LinkedBlockingQueue

```java
public class FixedThreadPool {

    public static void main(String[] args) {
        ExecutorService threadPool= Executors.newFixedThreadPool(4);
        for (int i = 0; i < 100; i++) {
            threadPool.execute(new SimpleTask1());
        }
        
    }

}
```

```java
public class SimpleTask1 implements  Runnable {

    @Override
    public void run() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName());
    }
}
```

运行 main 方法,  部分输出结果:&#x20;

```markup
pool-1-thread-3
pool-1-thread-1
pool-1-thread-2
pool-1-thread-4
pool-1-thread-4
pool-1-thread-3
pool-1-thread-1
pool-1-thread-2
pool-1-thread-2
pool-1-thread-1
pool-1-thread-3
pool-1-thread-4
pool-1-thread-4
pool-1-thread-1
```

可以看出, 无论我们往线程池里面加入多少任务, 都有且只有4个线程, 不会出现5个线程.

回想 FiexedThreadPool 的两个特性: 固定线程数量 和 无界队列. 我们很容易想到这类线程池的缺点. 假设每个任务的处理时间较长, 则未处理的任务则会一直存在于队列里面, 队列总会溢出的.&#x20;

我们稍微修改一下  FiexedThreadPool  和 SimpleTask1. 将每一个任务的时间设置的足够长, 将提交任务的数量设置的很多.

```java
public class FixedThreadPool {

    public static void main(String[] args) {
        ExecutorService threadPool= Executors.newFixedThreadPool(4);
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            threadPool.execute(new SimpleTask1());
        }
    }

}
```

```java
public class SimpleTask1 implements  Runnable {

    @Override
    public void run() {
        try {
            Thread.sleep(1000000000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName());
    }
}
```

运行结果:

```markup
Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "main"
```

抛出 OutOfMemoryError

## SingleThreadExecutor

创建一个只有一个线程的线程池, 内部使用无界队列 LinkedBlockingQueue,&#x20;

```
public class SingleThreadExecutor {

    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 100; i++) {
            threadPool.execute(new SimpleTask2());
        }

    }
    
}
```

```
public class SimpleTask2 implements  Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}
```

运行结果

```markup
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
```

可以看出永远只有一个线程在运行.&#x20;

同样的当请求堆积的时候, 会占用大量内存, 也可能导致 OutOfMemoryError, 这里就不演示了.

## CachedThreadPool

CachedThreadPool 的 corePoolSize 为0 ,maxPoolSize 无限大(最大整型), 使用SynchronousQueue 直接交接队列. 一定时间后(默认60s), 空闲的线程会被回收

```java
public class CachedThreadPool  {

    public static void main(String[] args) {
        ExecutorService threadPool= Executors.newCachedThreadPool();
        for (int i = 0; i < 100; i++) {
            System.out.println(i);
            threadPool.execute(new SimpleTask2());
        }
    }
}
```

```java
public class SimpleTask2 implements  Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}
```

部分运行结果:

```markup
pool-1-thread-112
pool-1-thread-111
pool-1-thread-112
pool-1-thread-39
pool-1-thread-60
pool-1-thread-14
pool-1-thread-64
pool-1-thread-14
pool-1-thread-64

```

可以看出, 最多时候有100多个线程, 但随后这些线程又被回收了, 不需要这么多.

同样的, 因为 maxPoolSize 被设置为了 Integer.MAX\_VALUE, 可能会创建数量非常多的线程, 导致 OutOfMemoryError.

## ScheduledThreadPool

corePoolSize 为0, maxPoolSize 为 Integer.MAX\_VALUE, 使用SynchronousQueue 直接交接队列

```java
public class ScheduledThreadPool {

    public static void main(String[] args) {
        ScheduledExecutorService  threadPool= Executors.newScheduledThreadPool(10);

        //用法1, 延迟5秒运行线程池
        threadPool.schedule(new SimpleTask2(),5, TimeUnit.SECONDS);

        //用法2, 延迟1秒运行线程池, 以后每隔三秒处理一个任务
        threadPool.scheduleAtFixedRate(new SimpleTask2(),1,3,TimeUnit.SECONDS);

    }

}
```

```java
public class SimpleTask2 implements  Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}
```

## 总结一下

<table><thead><tr><th width="150">参数</th><th width="150">FixedThreadPool</th><th width="150">CachedThreadPool</th><th>ScheduledThreadPool</th><th>SingleThreadPool</th></tr></thead><tbody><tr><td>corePoolSize</td><td>自定义</td><td>0</td><td>自定义</td><td>1</td></tr><tr><td>maxPoolSize</td><td>自定义</td><td>Integer.MAX_VALUE</td><td>Integer.MAX_VALUE</td><td>1</td></tr><tr><td>keepAliveTime</td><td>0</td><td>60s</td><td>0</td><td>0</td></tr><tr><td>workQueue</td><td>LinkedBlockingQueue</td><td>SynchronousQueue</td><td>DelayedWorkQueue</td><td>LinkedBlockingQueue</td></tr></tbody></table>

DelayedWorkQueue 延迟队列, 其底层是一个 堆.
