线程池之 Executor、Executors、ExecutorService、ThreadPoolExecutor

  线程池的核心是ThreadPoolExecutor。Executor、Executors、ExecutorService、AbstractExecutorService这些接口或类都是ThreadPoolExecutor的祖宗,下面分别进行阐述

一、Executor接口

  在源码中Executor是一个接口,这个接口只有一个方法void execute(Runnable command)方法。该方法提供一种将任务提交与每个任务将如何运行分离开来的方法。通常使用Executor的场景并不是显式地创建线程,而是只执行任务,实现线程的创建和线程的执行解耦。

// 传统的使用方案
    public static void main(String[] args) {
        new Thread(new Runnable() {

            @Override
            public void run() {
                System.out.println("新建工单消息提醒");
            }
        }, "新建工单线程").start();
        new Thread(new Runnable() {

            @Override
            public void run() {
                System.out.println("工单结单消息提醒");
            }
        }, "工单结单线程").start();
    }


// 使用Executor接口的方案
    public static void main(String[] args) {
        Executor executor = new ThreadPoolExecutor(5, 10, 3, TimeUnit.NANOSECONDS, null);
        executor.execute(new Runnable() {

            @Override
            public void run() {
                System.out.println("新建工单消息提醒");
            }
        });
        executor.execute(new Runnable() {

            @Override
            public void run() {
                System.out.println("工单结单消息提醒");
            }
        });
    }

上面代码可以看出来,不需要.start()两次,就可以创建线程出来。如此说来,个人感觉Executor更像是一个瓶起子,来一瓶啤酒,就开一瓶啤酒;不再像之前那样,为每一瓶啤酒,搞一个瓶起子。

二、ExecutorService接口

//一个接口继承另一个接口
public interface ExecutorService extends Executor{...}

  接口ExecutorService补充了十二个接口。因为它是接口,所以理所当然的并没有给出Executor接口中execute()方法的实现。Executors类为创建ExecutorService提供了便捷的工厂方法。ExecutorService还蛮重要的,看看它的衍生家族吧。

//接口ScheduledExecutorService继承了接口ExecutorService
public interface ScheduledExecutorService extends ExecutorService {...}


//创建newCachedThreadPool,返回ExecutorService
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

//创建newFixedThreadPool,返回ExecutorService
ExecutorServie fixedThreadPool = Executors.newFixedThreadPool();

//创建newSingleThreadExecutor(),返回ExecutorService
ExecutorService singleThreadPool = Executors.newSingleThreadExecutor());

//创建newWorkStealingPool,返回ExecutorService
ExecutoreService workStealingThreadPool = Executores.newWorkStealingPool());


//创建newScheduledThreadPool,返回ScheduledExecutorService
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool());

  接口ExecutorServie中有名如其义的几个方法:submit、shutdown、invokeAll、awaitTermination。使用代码如下:

package executors;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 网络服务的简单结构:这里线程池中的线程作为传入的请求。它使用了预先配置
 */
public class TestNetworkService {

}

class NetworkService implements Runnable {

    private final ServerSocket    serverSocket;
    private final ExecutorService threadPool;

    public NetworkService(int port, int poolSize) throws IOException{
        this.serverSocket = new ServerSocket(port);
        this.threadPool = Executors.newFixedThreadPool(poolSize);
    }

    @Override
    public void run() {
        try {
            for (;;) {
                threadPool.execute(new Handler(serverSocket.accept()));
            }
        } catch (IOException e) {
            threadPool.shutdown();
        }
    }

    public void shutdownAndAwaitTermination(ExecutorService pool) {
        // Disable new tasks from being submitted
        pool.shutdown();

        try {
            // 等待60秒后,任务还没执行完成,就调用 shutdownNow取消所有遗留的任务
            // Wait a while for existing tasks to terminate
            if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
                pool.shutdownNow();
                // Wait a while for tasks to respond to being cancelled
                if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
                    System.err.println("pool din't terminate");
                }
            }
        } catch (InterruptedException e) {
            // (Re-)Cancel if current thread also interrupted
            pool.shutdownNow();
            // Preserve interrupt status
            Thread.currentThread().interrupt();
        }
    }
}

class Handler implements Runnable {

    private final Socket socket;

    public Handler(Socket socket){
        super();
        this.socket = socket;
    }

    @Override
    public void run() {
        // TODO {read and service request on socket}
    }
}

三、ThreadPoolExecutor类(它是ExecutorService)的一个实现类

  线程池类为java.util.concurrent.ThreadPoolExecutor,常用的构造方法为:

 

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

 

  其参数的含义分别为:

  1.corePoolSize,线程池维护线程的最少数量

  2.maximunPoolSize,线程池维护线程的最大数量

  3.keepAliveTime,线程池维护线程所允许的空闲时间

  4.unit:线程池维护线程所允许的空闲时间的单位(TimeUnit.SECONDS;TimeUnit.MICROSECONDS;)

  5.workQueue:线程池所使用的缓冲队列,它常用的是:java.util.concurrent.ArrayBlockingQueue。

  6.handler:线程池对拒绝任务的处理策略。handler有四个选择:

    ThreadPoolExecutor.AbortPolicy();抛出java.util.concurrent.RejectedExecutionException异常。

    ThreadPoolExecutor.callerRunsPolicy();重复添加当前任务,它会自动重复调用execute()方法。

    ThreadPoolExecutor.DiscardOldesetPolicy();抛弃旧的任务

    ThreadPoolExecutor.DiscardPolicy();抛弃当前的任务

一个任务通过execute(Runnable)方法被添加到线程池,任务就是一个Runnable类型的对象,任务的执行方法就是Runnable类型对象的run()方法,当一个任务通过execute(Runnable)方法欲添加到线程池时:

    如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。

    如果此时线程池中的数量等于corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。

    如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理任务。

    如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。也就是:处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。

    如果当线程池中的线程数量大于corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数

 

 

 

 

 

 

 

 

参考:

博客:http://blog.csdn.net/linghu_java/article/details/17123057

http://cuisuqiang.iteye.com/blog/2019372

http://www.cnblogs.com/dolphin0520/p/3932921.html

 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值