Executor的介绍及线程池的应用

2022-11-02 14:57:08 浏览数 (3)

1、Executor

  • Executor的相关关系图

Executors少了一个创建线程池的方法newScheduledThreadPool()

  • 继承和实现关系
代码语言:javascript复制
public interface ExecutorService extends Executor {}
public abstract class AbstractExecutorService implements ExecutorService {}
public interface ScheduledExecutorService extends ExecutorService {}
public class ThreadPoolExecutor extends AbstractExecutorService {}
public class ScheduledThreadPoolExecutor extends ThreadPoolExecutor implements ScheduledExecutorService {}
代码语言:javascript复制
区别:

  1.ExecutorService 接口继承了Executor 接口,是Executor 的子接口。


  2.Executor接口中定义了execute()方法,用来接收一个Runnable接口的对象,

       而ExecutorService接口中定义的submit()方法可以接收Runnable和Callable接口对象。


  3.Executor接口中execute()方法不返回任何结果,而ExecutorService接口中submit()方法可以通过一个 Future 对象返回运算结果。


  4.Executor和ExecutorService除了允许客户端提交一个任务,ExecutorService 还提供用来控制线程池的方法。

       比如:调用 shutDown() 方法终止线程池。

  5.Executors 类提供工厂方法用来创建不同类型的线程池。比如: 

     newSingleThreadExecutor() 创建一个只有一个线程的线程池,

     newFixedThreadPool(int numOfThreads)来创建固定线程数的线程池,

     newCachedThreadPool()创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

     newScheduledThreadPool(int corePoolSize) 创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
  • Executors简介
    • Executors 是一个工厂类,其提供的是Executor、ExecutorService、ScheduledExecutorService、ThreadFactory 和 Callable 类的实例的工厂方法;
    • 提供常用配置的 ExecutorService、ScheduledExecutorService的实现方法;
    • 创建并返回 ThreadFactory 的方法,它可将新创建的线程设置为已知的状态。
    • 将其他非Callable接口的其他类对象,封装成Callable,从而用于默些方法;

2、创建线程池

上面图例和补充里有创建线程池的四种方式。

1. newCachedThreadPool(创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。线程池为无限大)

代码语言:javascript复制
    public static void main(String[] args) {
        // 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
        Executor cachedThreadPool = Executors.newCachedThreadPool();
        // 循环10次
        for (int i = 0; i < 10; i  ) {
            // 初始化index作为线程内输出,要求final
            final int index = i;
            // 等待,让前一个线程执行完成
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 执行任务
            cachedThreadPool.execute(new Runnable() {

                @Override
                public void run() {
                    // 输出线程名称
                    System.out.println(index " 线程名称:" Thread.currentThread().getName());
                }
            });
        }
    }

结果:

可以看到使用的一个线程进行的输出,证明在线程执行完成后会被回收重新执行安排的任务

2. newFixedThreadPool(创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

代码语言:javascript复制
    public static void main(String[] args) {
        // 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 10; i  ) {
            final int index = i;
            fixedThreadPool.execute(new Runnable() {
                public void run() {
                    try {
                        System.out.println(index);
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        fixedThreadPool.shutdown();
    }

结果:

我们给定长线程池设置了3个线程,就一直是这三个线程在跑

3. newScheduledThreadPool(创建一个定长线程池,支持定时及周期性任务执行。

代码语言:javascript复制
    public static void main(String[] args) {
        // 创建一个定长线程池,支持定时及周期性任务执行。
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
        for (int i = 0; i < 10; i  ) {
            scheduledThreadPool.schedule(new Runnable() {
                public void run() {
                    System.out.println("delay 3 seconds " Thread.currentThread().getName());
                }
            }, 3, TimeUnit.SECONDS);// 3s以后执行
        }
        scheduledThreadPool.shutdown();
    }

结果:

线程池有5个线程,并且在启动后3s后才去执行内容

4.newSingleThreadExecutor (按顺序来执行线程任务   但是不同于单线程,这个线程池只是只能存在一个线程,这个线程死后另外一个线程会补上,继续按顺序执行任务。)

代码语言:javascript复制
public static void main(String[] args) {
        /**
         * 单线程化的线程池
         */
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i  ) {
            final int index = i;
            singleThreadExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    Thread.currentThread().setName("Thread i = "   index);
                    System.out.println(Thread.currentThread().getName()   " index = "   index);
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        System.out.println("ssss");
                    }
                }
            });
        }
        singleThreadExecutor.shutdown();
        System.out.println("on the main thread...");

    }

0 人点赞