ExecutorService线程池

本文详细介绍了如何使用ExecutorService建立多线程,包括定义线程类、创建线程池以及线程池的操作。同时,文章还讨论了几种不同的ExecutorService线程池对象及其适用场景,如缓存型池子、固定线程池、调度型线程池和单例线程池。此外,还介绍了自定义线程工厂和如何通过Executor的execute()方法执行任务。

转载:http://blog.sina.com.cn/s/blog_6151984a0100krj8.html

 

ExecutorService 建立多线程的步骤:

1。定义线程类class Handler implements Runnable{
}
2。建立ExecutorService线程池ExecutorService executorService = Executors.newCachedThreadPool();

或者

int cpuNums = Runtime.getRuntime().availableProcessors();
                //获取当前系统的CPU 数目
ExecutorService executorService =Executors.newFixedThreadPool(cpuNums * POOL_SIZE);
                //ExecutorService通常根据系统资源情况灵活定义线程池大小
3。调用线程池操作循环操作,成为daemon,把新实例放入Executor池中
      while(true){
        executorService.execute(new Handler(socket)); 
           // class Handler implements Runnable{
        或者
        executorService.execute(createTask(i));
            //private static Runnable createTask(final int taskID)
      }

execute(Runnable对象)方法
其实就是对Runnable对象调用start()方法
(当然还有一些其他后台动作,比如队列,优先级,IDLE timeout,active激活等)



几种不同的ExecutorService线程池对象

1.newCachedThreadPool() -缓存型池子,先查看池中有没有以前建立的线程,如果有,就reuse.如果没有,就建一个新的线程加入池中
-缓存型池子通常用于执行一些生存期很短的异步型任务
 因此在一些面向连接的daemon型SERVER中用得不多。
-能reuse的线程,必须是timeout IDLE内的池中线程,缺省timeout是60s,超过这个IDLE时长,线程实例将被终止及移出池。
  注意,放入CachedThreadPool的线程不必担心其结束,超过TIMEOUT不活动,其会自动被终止。
2. newFixedThreadPool-newFixedThreadPool与cacheThreadPool差不多,也是能reuse就用,但不能随时建新的线程
-其独特之处:任意时间点,最多只能有固定数目的活动线程存在,此时如果有新的线程要建立,只能放在另外的队列中等待直到当前的线程中某个线程终止直接被移出池子
-和cacheThreadPool不同,FixedThreadPool没有IDLE机制(可能也有,但既然文档没提,肯定非常长,类似依赖上层的TCP或UDP IDLE机制之类的),所以FixedThreadPool多数针对一些很稳定很固定的正规并发线程,多用于服务器
-从方法的源代码看,cache池和fixed 池调用的是同一个底层池,只不过参数不同:
fixed池线程数固定,并且是0秒IDLE(无IDLE)
cache池线程数支持0-Integer.MAX_VALUE(显然完全没考虑主机的资源承受能力),60秒IDLE  
3.ScheduledThreadPool-调度型线程池
-这个池子里的线程可以按schedule依次delay执行,或周期执行
4.SingleThreadExecutor-单例线程,任意时间池中只能有一个线程
-用的是和cache池和fixed池相同的底层池,但线程数目是1-1,0秒IDLE(无IDLE)



上面四种线程池,都使用Executor的缺省线程工厂建立线程,也可单独定义自己的线程工厂
下面是缺省线程工厂代码:

    static class DefaultThreadFactory implements ThreadFactory {
        static final AtomicInteger poolNumber = new AtomicInteger(1);
        final ThreadGroup group;
        final AtomicInteger threadNumber = new AtomicInteger(1);
        final String namePrefix;

        DefaultThreadFactory() {
            SecurityManager s = System.getSecurityManager();
            group = (s != null)? s.getThreadGroup() :Thread.currentThread().getThreadGroup();
          
            namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-";
        }

        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r,namePrefix + threadNumber.getAndIncrement(),0);
            if (t.isDaemon())
                t.setDaemon(false);
            if (t.getPriority() != Thread.NORM_PRIORITY)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }

 

也可自己定义ThreadFactory,加入建立池的参数中

 public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {



Executor的execute()方法
execute() 方法将Runnable实例加入pool中,并进行一些pool size计算和优先级处理
execute() 方法本身在Executor接口中定义,有多个实现类都定义了不同的execute()方法
如ThreadPoolExecutor类(cache,fiexed,single三种池子都是调用它)的execute方法如下:

    public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {
            if (runState == RUNNING && workQueue.offer(command)) {
                if (runState != RUNNING || poolSize == 0)
                    ensureQueuedTaskHandled(command);
            }
            else if (!addIfUnderMaximumPoolSize(command))
                reject(command); // is shutdown or saturated
        }
    }



<think> 我们参考用户提供的引用资料,特别是引用[1]和引用[4]中的示例,来构建一个ExecutorService线程池在业务中使用的完整示例。 用户希望看到的是业务中使用的示例,因此我们将模拟一个常见的业务场景:并发处理多个订单任务。 场景描述: 假设我们有一个订单处理系统,需要同时处理多个订单。每个订单的处理包括以下步骤: 1. 验证订单信息 2. 计算订单金额(可能涉及远程调用,这里用睡眠模拟耗时) 3. 保存订单到数据库(模拟) 我们将使用ExecutorService线程池来并发处理这些订单任务,提高处理效率。 注意点: 1. 使用ThreadPoolExecutor创建线程池,并合理配置参数(核心线程数、最大线程数、队列容量等) 2. 使用submit提交Callable任务(因为需要返回处理结果) 3. 获取每个订单处理的结果(Future对象)并处理可能的异常 4. 优雅关闭线程池 示例代码: </think>以下是一个基于业务场景的`ExecutorService`线程池使用完整示例,模拟电商系统中的订单处理流程: ```java import java.util.concurrent.*; import java.util.*; public class OrderProcessingSystem { // 订单处理服务(模拟业务逻辑) static class OrderService { public String processOrder(String orderId) throws InterruptedException { // 模拟业务处理时间(50-150ms) int processTime = 50 + new Random().nextInt(100); Thread.sleep(processTime); // 返回处理结果(实际业务可能包含数据库操作等) return String.format("订单[%s]处理完成 | 耗时:%dms | 线程:%s", orderId, processTime, Thread.currentThread().getName()); } } public static void main(String[] args) throws InterruptedException { // 1. 创建线程池(根据业务需求配置) ThreadPoolExecutor executor = new ThreadPoolExecutor( 4, // 核心线程数(日常负载) 10, // 最大线程数(应对流量高峰) 30, TimeUnit.SECONDS, // 空闲线程存活时间 new LinkedBlockingQueue<>(50), // 任务队列容量 new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略 ); OrderService orderService = new OrderService(); List<Future<String>> futures = new ArrayList<>(); Scanner scanner = new Scanner(System.in); System.out.print("请输入要生成的订单数量: "); int orderCount = scanner.nextInt(); // 2. 提交订单处理任务 for (int i = 1; i <= orderCount; i++) { String orderId = "ORD2023" + String.format("%05d", i); futures.add(executor.submit(() -> { try { return orderService.processOrder(orderId); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return "订单处理被中断: " + orderId; } })); } // 3. 监控线程池状态(业务系统常用) new Thread(() -> { while (!executor.isTerminated()) { System.out.printf("\n[监控] 活动线程: %d | 队列任务: %d | 完成订单: %d", executor.getActiveCount(), executor.getQueue().size(), executor.getCompletedTaskCount()); try { Thread.sleep(2000); } catch (InterruptedException ignored) {} } }).start(); // 4. 获取处理结果 System.out.println("\n\n=== 订单处理结果 ==="); for (Future<String> future : futures) { try { // 设置超时防止阻塞 System.out.println(future.get(500, TimeUnit.MILLISECONDS)); } catch (TimeoutException e) { System.err.println("订单处理超时,转人工处理"); } catch (Exception e) { System.err.println("系统错误: " + e.getCause().getMessage()); } } // 5. 优雅关闭线程池 executor.shutdown(); if (!executor.awaitTermination(10, TimeUnit.SECONDS)) { List<Runnable> unfinished = executor.shutdownNow(); System.err.println("强制关闭,未完成订单: " + unfinished.size()); } System.out.println("=== 所有订单处理完成 ==="); } } ``` ### 业务场景关键点说明: 1. **线程池配置** ```java new ThreadPoolExecutor(4, 10, 30, SECONDS, new LinkedBlockingQueue<>(50), new CallerRunsPolicy()) ``` - 核心线程数4:日常订单处理能力 - 最大线程数10:应对促销高峰流量 - 队列容量50:缓冲突发流量[^1] - 拒绝策略:当系统过载时,由提交线程处理订单(避免丢弃订单) 2. **订单处理流程** ```java executor.submit(() -> orderService.processOrder(orderId)) ``` - 每个订单作为独立任务提交 - 使用Callable返回处理结果 - 异常捕获保证任务稳定性 3. **生产级特性** - **实时监控**:独立线程监控线程池状态 ```java executor.getActiveCount() // 活动线程数 executor.getQueue().size() // 排队任务数 ``` - **超时控制**:防止个别订单阻塞系统 ```java future.get(500, TimeUnit.MILLISECONDS) ``` - **优雅关闭**: ```java executor.shutdown(); // 停止接收新订单 executor.awaitTermination(10, SECONDS); // 等待现有订单完成 executor.shutdownNow(); // 强制终止(最后手段) ``` ### 运行示例: ``` 请输入要生成的订单数量: 15 [监控] 活动线程: 4 | 队列任务: 11 | 完成订单: 0 [监控] 活动线程: 4 | 队列任务: 7 | 完成订单: 4 === 订单处理结果 === 订单[ORD202300001]处理完成 | 耗时:72ms | 线程:pool-1-thread-2 订单[ORD202300002]处理完成 | 耗时:112ms | 线程:pool-1-thread-1 ... 订单[ORD202300015]处理完成 | 耗时:98ms | 线程:pool-1-thread-4 [监控] 活动线程: 0 | 队列任务: 0 | 完成订单: 15 === 所有订单处理完成 === ``` ### 业务实践建议: 1. **参数调优**:根据系统监控调整核心参数 2. **命名线程**:使用`ThreadFactory`命名线程便于排查问题 ```java new ThreadFactoryBuilder().setNameFormat("Order-Thread-%d").build() ``` 3. **异常处理**:添加`UncaughtExceptionHandler`捕获未处理异常 4. **资源隔离**:不同业务使用独立线程池避免相互影响[^2]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值