Java线程池的使用

Executors类有以下几个方法
1、public static ExecutorService newFixedThreadPool(int nThreads):创建一个可重用的、具有固定线程数的线程池。
2、public static ExecutorService newSingleThreadExecutor():创建一个只有单线程的线程池,它相当于newFixedThreadPool方法是传入的参数为1
3、public static ExecutorService newCachedThreadPool():创建一个具有缓存功能的线程池,系统根据需要创建线程,这些线程将会被缓存在线程池中。
4、public static ScheduledExecutorService newSingleThreadScheduledExecutor:创建只有一条线程的线程池,他可以在指定延迟后执行线程任务

5、public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize):创建具有指定线程数的线程池,它可以再指定延迟后执行线程任务,corePoolSize指池中所保存的线程数,即使线程是空闲的也被保存在线程池内。

一、简单使用

1) 建立测试用执行类

public class PoolRunner implements Runnable {

    private final String name;

    public PoolRunner(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        String dateTime = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS").format(new Date());
        System.out.println("DateTime:" + dateTime + " Name:" + name + " ThreadName:" + Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            System.out.println(ex.getMessage());
        }
    }
}


2)newFixedThreadPool

        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
        for(int i=0;i<10;i++){
            fixedThreadPool.execute(new PoolRunner("name" + i));
        }
        fixedThreadPool.shutdown();
执行结果:
DateTime:2015-06-26 10:49:33.530 Name:name3 ThreadName:pool-1-thread-4
DateTime:2015-06-26 10:49:33.530 Name:name0 ThreadName:pool-1-thread-1
DateTime:2015-06-26 10:49:33.530 Name:name4 ThreadName:pool-1-thread-5
DateTime:2015-06-26 10:49:33.530 Name:name2 ThreadName:pool-1-thread-3
DateTime:2015-06-26 10:49:33.530 Name:name1 ThreadName:pool-1-thread-2
DateTime:2015-06-26 10:49:34.530 Name:name5 ThreadName:pool-1-thread-2
DateTime:2015-06-26 10:49:34.530 Name:name6 ThreadName:pool-1-thread-4
DateTime:2015-06-26 10:49:34.530 Name:name7 ThreadName:pool-1-thread-5
DateTime:2015-06-26 10:49:34.530 Name:name8 ThreadName:pool-1-thread-3
DateTime:2015-06-26 10:49:34.530 Name:name9 ThreadName:pool-1-thread-1
可以看出线程池中总共有5个线程,每个线程执行了2次任务,间隔1秒(由于Run方法中的Sleep)


3)newSingleThreadExecutor

        ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
        for(int i=0;i<10;i++){
            singleThreadPool.execute(new PoolRunner("name" + i));
        }
        singleThreadPool.shutdown();
执行结果:

DateTime:2015-06-26 10:54:27.937 Name:name0 ThreadName:pool-1-thread-1
DateTime:2015-06-26 10:54:28.937 Name:name1 ThreadName:pool-1-thread-1
DateTime:2015-06-26 10:54:29.937 Name:name2 ThreadName:pool-1-thread-1
DateTime:2015-06-26 10:54:30.937 Name:name3 ThreadName:pool-1-thread-1
DateTime:2015-06-26 10:54:31.937 Name:name4 ThreadName:pool-1-thread-1
DateTime:2015-06-26 10:54:32.937 Name:name5 ThreadName:pool-1-thread-1
DateTime:2015-06-26 10:54:33.937 Name:name6 ThreadName:pool-1-thread-1
DateTime:2015-06-26 10:54:34.937 Name:name7 ThreadName:pool-1-thread-1
DateTime:2015-06-26 10:54:35.937 Name:name8 ThreadName:pool-1-thread-1
DateTime:2015-06-26 10:54:36.937 Name:name9 ThreadName:pool-1-thread-1
只有一个线程


4)newCachedThreadPool

        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        for(int i=0;i<10;i++){
            cachedThreadPool.execute(new PoolRunner("name" + i));
        }
        cachedThreadPool.shutdown();
执行结果:

DateTime:2015-06-26 10:56:28.415 Name:name4 ThreadName:pool-1-thread-5
DateTime:2015-06-26 10:56:28.415 Name:name2 ThreadName:pool-1-thread-3
DateTime:2015-06-26 10:56:28.415 Name:name9 ThreadName:pool-1-thread-10
DateTime:2015-06-26 10:56:28.415 Name:name6 ThreadName:pool-1-thread-7
DateTime:2015-06-26 10:56:28.415 Name:name0 ThreadName:pool-1-thread-1
DateTime:2015-06-26 10:56:28.415 Name:name3 ThreadName:pool-1-thread-4
DateTime:2015-06-26 10:56:28.415 Name:name1 ThreadName:pool-1-thread-2
DateTime:2015-06-26 10:56:28.415 Name:name7 ThreadName:pool-1-thread-8
DateTime:2015-06-26 10:56:28.415 Name:name5 ThreadName:pool-1-thread-6
DateTime:2015-06-26 10:56:28.415 Name:name8 ThreadName:pool-1-thread-9
总共建立了10个线程


5)newScheduledThreadPool

        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
        for (int i = 0; i < 10; i++) {
            String name = "name" + i;
            String dateTime = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS").format(new Date());
            System.out.println("ScheduledTime:" + dateTime + " Name:" + name);
            scheduledThreadPool.schedule(new PoolRunner(name), 1, TimeUnit.SECONDS);
        }
        scheduledThreadPool.shutdown();

schedule方法的第二个参数代表延迟多少时间执行,时间单位由最后一个参数决定

执行结果:

ScheduledTime:2015-06-26 10:59:12.576 Name:name0
ScheduledTime:2015-06-26 10:59:12.576 Name:name1
ScheduledTime:2015-06-26 10:59:12.576 Name:name2
ScheduledTime:2015-06-26 10:59:12.576 Name:name3
ScheduledTime:2015-06-26 10:59:12.576 Name:name4
ScheduledTime:2015-06-26 10:59:12.576 Name:name5
ScheduledTime:2015-06-26 10:59:12.576 Name:name6
ScheduledTime:2015-06-26 10:59:12.576 Name:name7
ScheduledTime:2015-06-26 10:59:12.576 Name:name8
ScheduledTime:2015-06-26 10:59:12.576 Name:name9
DateTime:2015-06-26 10:59:13.586 Name:name0 ThreadName:pool-1-thread-4
DateTime:2015-06-26 10:59:13.586 Name:name3 ThreadName:pool-1-thread-3
DateTime:2015-06-26 10:59:13.586 Name:name2 ThreadName:pool-1-thread-2
DateTime:2015-06-26 10:59:13.586 Name:name1 ThreadName:pool-1-thread-5
DateTime:2015-06-26 10:59:13.586 Name:name4 ThreadName:pool-1-thread-1
DateTime:2015-06-26 10:59:14.586 Name:name5 ThreadName:pool-1-thread-1
DateTime:2015-06-26 10:59:14.586 Name:name7 ThreadName:pool-1-thread-3
DateTime:2015-06-26 10:59:14.586 Name:name6 ThreadName:pool-1-thread-5
DateTime:2015-06-26 10:59:14.586 Name:name8 ThreadName:pool-1-thread-2
DateTime:2015-06-26 10:59:14.586 Name:name9 ThreadName:pool-1-thread-4
创建了保持5个线程的线程池,线程执行延迟1秒执行

6)newSingleThreadScheduledExecutor

ScheduledExecutorService singleScheduledThreadPool = Executors.newSingleThreadScheduledExecutor();
        for (int i = 0; i < 10; i++) {
            String name = "name" + i;
            String dateTime = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS").format(new Date());
            System.out.println("ScheduledTime:" + dateTime + " Name:" + name);
            singleScheduledThreadPool.schedule(new PoolRunner(name), 1, TimeUnit.SECONDS);
        }
        singleScheduledThreadPool.shutdown();
执行结果:

ScheduledTime:2015-06-26 11:02:06.652 Name:name0
ScheduledTime:2015-06-26 11:02:06.662 Name:name1
ScheduledTime:2015-06-26 11:02:06.662 Name:name2
ScheduledTime:2015-06-26 11:02:06.662 Name:name3
ScheduledTime:2015-06-26 11:02:06.662 Name:name4
ScheduledTime:2015-06-26 11:02:06.662 Name:name5
ScheduledTime:2015-06-26 11:02:06.662 Name:name6
ScheduledTime:2015-06-26 11:02:06.662 Name:name7
ScheduledTime:2015-06-26 11:02:06.662 Name:name8
ScheduledTime:2015-06-26 11:02:06.662 Name:name9
DateTime:2015-06-26 11:02:07.672 Name:name0 ThreadName:pool-1-thread-1
DateTime:2015-06-26 11:02:08.674 Name:name1 ThreadName:pool-1-thread-1
DateTime:2015-06-26 11:02:09.674 Name:name2 ThreadName:pool-1-thread-1
DateTime:2015-06-26 11:02:10.674 Name:name3 ThreadName:pool-1-thread-1
DateTime:2015-06-26 11:02:11.678 Name:name4 ThreadName:pool-1-thread-1
DateTime:2015-06-26 11:02:12.678 Name:name5 ThreadName:pool-1-thread-1
DateTime:2015-06-26 11:02:13.679 Name:name6 ThreadName:pool-1-thread-1
DateTime:2015-06-26 11:02:14.686 Name:name7 ThreadName:pool-1-thread-1
DateTime:2015-06-26 11:02:15.686 Name:name8 ThreadName:pool-1-thread-1
DateTime:2015-06-26 11:02:16.688 Name:name9 ThreadName:pool-1-thread-1
延迟1秒执行,但是只有一个单独的线程

二、ThreadFactory

所以线程池的初始化方法都可以自定义ThreadFactory

这样就可以在初始化线程的时候做一些设定,比如使用setUncaughtExceptionHandler对异常进行处理、写入Log。

实现一个更改线程名的ThreadFactory作为测试:

public class ErrorRunner implements Runnable  {

    @Override
    public void run() {
        throw new RuntimeException("Thread Exception Test."); 
    } 
}

public class MyThreadFactory implements ThreadFactory {

    @Override
    public Thread newThread(Runnable r) {
        Thread thread = new Thread(r);
        thread.setUncaughtExceptionHandler(new UncaughtExceptionHandlerImpl());
        return thread;
    }

    private static class UncaughtExceptionHandlerImpl implements UncaughtExceptionHandler {
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            System.out.println(t.getName() + " error:" + e.getMessage());
        }
    }
}
创建线程池:

        ExecutorService singleThreadPool = Executors.newSingleThreadExecutor(new MyThreadFactory());
        singleThreadPool.execute(new ErrorRunner());
        singleThreadPool.shutdown();
执行结果:

run:
Thread-0 error:Thread Exception Test.

三、定时计划循环执行
1)scheduleAtFixedRate和scheduleWithFixedDelay的区别

scheduleAtFixedRate严格按照指定的时间间隔执行任务。如果任务的执行时间大于指定的时间间隔,则在上一个任务结束后直接启动下一个任务

scheduleWithFixedDelay在上一个任务结束以后,再等待指定的间隔时间,才会启动下一个任务

示例:

2)scheduleAtFixedRate

        ScheduledExecutorService singleScheduledThreadPool = Executors.newSingleThreadScheduledExecutor();
        String name = "LoopTest";
        String dateTime = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS").format(new Date());
        System.out.println("ScheduledTime:" + dateTime + " Name:" + name);
        singleScheduledThreadPool.scheduleAtFixedRate(new PoolRunner(name), 1, 2, TimeUnit.SECONDS);
        Thread.sleep(10000);
        System.out.println("ShutDown!");
        singleScheduledThreadPool.shutdown();
scheduleAtFixedRate第三个参数代表设定的时间间隔

注意上面建立的PoolRunner类的Run方法中会Sleep 1秒

执行结果:

run:
ScheduledTime:2015-06-26 11:49:45.752 Name:LoopTest
DateTime:2015-06-26 11:49:46.744 Name:LoopTest ThreadName:pool-1-thread-1
DateTime:2015-06-26 11:49:48.767 Name:LoopTest ThreadName:pool-1-thread-1
DateTime:2015-06-26 11:49:50.767 Name:LoopTest ThreadName:pool-1-thread-1
DateTime:2015-06-26 11:49:52.767 Name:LoopTest ThreadName:pool-1-thread-1
DateTime:2015-06-26 11:49:54.767 Name:LoopTest ThreadName:pool-1-thread-1
DateTime:2015-06-26 11:49:56.767 Name:LoopTest ThreadName:pool-1-thread-1
DateTime:2015-06-26 11:49:58.768 Name:LoopTest ThreadName:pool-1-thread-1
ShutDown!
每次执行间隔2秒钟

PoolRunner类的Run方法中会Sleep改为3秒后再次执行

执行结果:

run:
ScheduledTime:2015-06-26 11:52:32.625 Name:LoopTest
DateTime:2015-06-26 11:52:33.635 Name:LoopTest ThreadName:pool-1-thread-1
DateTime:2015-06-26 11:52:36.636 Name:LoopTest ThreadName:pool-1-thread-1
DateTime:2015-06-26 11:52:39.641 Name:LoopTest ThreadName:pool-1-thread-1
DateTime:2015-06-26 11:52:42.647 Name:LoopTest ThreadName:pool-1-thread-1
DateTime:2015-06-26 11:52:45.647 Name:LoopTest ThreadName:pool-1-thread-1
ShutDown!
执行间隔变为3秒

3)scheduleWithFixedDelay

PoolRunner类的Run方法中会Sleep改1秒后执行如下代码

        ScheduledExecutorService singleScheduledThreadPool = Executors.newSingleThreadScheduledExecutor();
        String name = "LoopTest";
        String dateTime = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS").format(new Date());
        System.out.println("ScheduledTime:" + dateTime + " Name:" + name);
        singleScheduledThreadPool.scheduleWithFixedDelay(new PoolRunner(name), 1, 2, TimeUnit.SECONDS);
        Thread.sleep(10000);
        System.out.println("ShutDown!");
        singleScheduledThreadPool.shutdown();
执行结果:

run:
ScheduledTime:2015-06-26 11:54:50.718 Name:LoopTest
DateTime:2015-06-26 11:54:51.726 Name:LoopTest ThreadName:pool-1-thread-1
DateTime:2015-06-26 11:54:54.733 Name:LoopTest ThreadName:pool-1-thread-1
DateTime:2015-06-26 11:54:57.743 Name:LoopTest ThreadName:pool-1-thread-1
ShutDown!

可以看到执行间隔依然为3秒,因为scheduleWithFixedDelay方法会在每次任务执行结束(耗时1秒)后再等待2秒,才会启动下一次任务


4. submit 方法

Callable中的call()方法类似Runnable的run()方法。但是call()方法有返回值,run()方法没有。

使用submit方法,就可以从方法返回的Future对象中取得返回值的内容。

示例:

public class PoolCaller implements Callable<String> {

    private final String name;

    public PoolCaller(String name) {
        this.name = name;
    }

    @Override
    public String call() throws Exception {
        String dateTime = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS").format(new Date());
        String result = "DateTime:" + dateTime + " Name:" + name + " ThreadName:" + Thread.currentThread().getName();
        Thread.sleep(1000);
        return result;
    }
}
        ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
        Future<String> submit = singleThreadPool.submit(new PoolCaller("SubmitTest"));
        System.out.println(System.currentTimeMillis());
        System.out.println(submit.get());
        System.out.println(System.currentTimeMillis());
        singleThreadPool.shutdown();
执行结果:

run:
1435297292530
DateTime:2015-06-26 01:41:32.560 Name:SubmitTest ThreadName:pool-1-thread-1
1435297293560
可以看出来,Future的get方法会等待任务执行完成,然后返回call方法的返回值。

Future<?> submit(Runnable task)返回的Future对象调用get时会返回null

<T> Future<T> submit(Runnable task, T result)方法则会把传入的result的对象再返回出来


5. invokeAll方法

当要执行多个Callable的时候则可以使用invokeAll方法,它会在所有任务执行完以后返回一个Future的List

示例:

public class PoolCaller implements Callable<String> {

    private final String name;

    public PoolCaller(String name) {
        this.name = name;
    }

    @Override
    public String call() throws Exception {
        String dateTime = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS").format(new Date());
        String result = "DateTime:" + dateTime + " Name:" + name + " ThreadName:" + Thread.currentThread().getName();
        System.out.println(result);
        Thread.sleep(1000);
        return name + " is done!";
    }
}
        ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
        List<PoolCaller> list = new ArrayList(){{
            add(new PoolCaller("invokeAll-1"));
            add(new PoolCaller("invokeAll-2"));
        }};
        List<Future<String>> result = singleThreadPool.invokeAll(list);
        for(Future<String> future: result){
            System.out.println(future.get());
        }
        singleThreadPool.shutdown();
执行结果:

run:
DateTime:2015-06-26 02:08:46.309 Name:invokeAll-1 ThreadName:pool-1-thread-1
DateTime:2015-06-26 02:08:47.309 Name:invokeAll-2 ThreadName:pool-1-thread-1
invokeAll-1 is done!
invokeAll-2 is done!

另外invokeAll方法还有一个设置timout的重载,如果超过时间则会将已经完成的task返回,未完成的取消。

invokeAny方法则会任意执行传入的一组task中的任意一个。


源码来自:https://pan.quark.cn/s/a4b39357ea24 ### 操作指南:洗衣机使用方法详解#### 1. 启动与水量设定- **使用方法**:使用者必须首先按下洗衣设备上的“启动”按键,同时依据衣物数量设定相应的“水量选择”旋钮(高、中或低水量)。这一步骤是洗衣机运行程序的开端。- **运作机制**:一旦“启动”按键被触发,洗衣设备内部的控制系统便会启动,通过感应器识别水量选择旋钮的位置,进而确定所需的水量高度。- **技术执行**:在当代洗衣设备中,这一流程一般由微处理器掌管,借助电磁阀调控进水量,直至达到指定的高度。#### 2. 进水过程- **使用说明**:启动后,洗衣设备开始进水,直至达到所选的水位(高、中或低)。- **技术参数**:水量的监测通常采用浮子式水量控制器或压力感应器来实现。当水位达到预定值时,进水阀会自动关闭,停止进水。- **使用提醒**:务必确保水龙头已开启,并检查水管连接是否牢固,以防止漏水。#### 3. 清洗过程- **使用步骤**:2秒后,洗衣设备进入清洗环节。在此期间,滚筒会执行一系列正转和反转的动作: - 正转25秒 - 暂停3秒 - 反转25秒 - 再次暂停3秒- **重复次数**:这一系列动作将重复执行5次,总耗时为280秒。- **技术关键**:清洗环节通过电机驱动滚筒旋转,利用水流冲击力和洗衣液的化学效果,清除衣物上的污垢。#### 4. 排水与甩干- **使用步骤**:清洗结束后,洗衣设备会自动进行排水,将污水排出,然后进入甩干阶段,甩干时间为30秒。- **技术应用**:排水是通过泵将水抽出洗衣设备;甩干则是通过高速旋转滚筒,利用离心力去除衣物上的水分。- **使用提醒**:...
代码下载地址: https://pan.quark.cn/s/c289368a8f5c 在安卓应用开发领域,构建一个高效且用户友好的聊天系统是一项核心任务。 为了协助开发者们迅速达成这一目标,本文将分析几种常见的安卓聊天框架,并深入说明它们的功能特性、应用方法及主要优势。 1. **环信(Easemob)** 环信是一个专为移动应用打造的即时通讯软件开发套件,涵盖了文本、图片、语音、视频等多种消息形式。 通过整合环信SDK,开发者能够迅速构建自身的聊天平台。 环信支持消息内容的个性化定制,能够应对各种复杂的应用场景,并提供多样的API接口供开发者使用。 2. **融云(RongCloud)** 融云作为国内领先的IM云服务企业,提供了全面的聊天解决方案,包括一对一交流、多人群聊、聊天空间等。 融云的突出之处在于其稳定运行和高并发处理性能,以及功能完备的后台管理工具,便于开发者执行用户管理、消息发布等操作。 再者,融云支持多种消息格式,如位置信息、文件传输、表情符号等,显著增强了用户聊天体验。 3. **Firebase Cloud Messaging(FCM)** FCM由Google提供的云端消息传递服务,可达成安卓设备与服务器之间的即时数据交换。 虽然FCM主要应用于消息推送,但配合Firebase Realtime Database或Firestore数据库,开发者可以开发基础的聊天软件。 FCM的显著优势在于其全球性的推送网络,保障了消息能够及时且精确地传输至用户。 4. **JMessage(极光推送)** 极光推送是一款提供消息发布服务的软件开发工具包,同时具备基础的即时通讯能力。 除了常规的文字、图片信息外,极光推送还支持个性化消息,使得开发者能够实现更为复杂的聊天功能。 此...
<think>好的,我需要回答用户关于如何在Java使用线程池的问题,包括示例代码和最佳实践。首先,我应该回顾用户提供的引用内容,看看有没有相关的信息可以利用。 根据引用[1],提到了Java线程池使用实例、最佳实践以及代码示例。引用[2]讨论了为什么使用线程池、如何使用以及遇到的坑。引用[3]则集中在最佳实践和异常处理方面。这些引用应该能提供足够的信息来构建回答。 首先,我需要解释线程池的基本概念和为什么要使用线程池,比如资源复用、控制并发数、管理线程生命周期等。然后,介绍Java中创建线程池的方法,特别是通过Executors工厂类提供的几种常见线程池类型,比如FixedThreadPool、CachedThreadPool、SingleThreadExecutor等,但也要提到推荐直接使用ThreadPoolExecutor来创建,以便更灵活地控制参数,避免资源耗尽的风险,这点在引用[3]中有提到。 接下来,给出一个示例代码。根据引用[1]中的示例,可能需要展示如何通过ThreadPoolExecutor来创建线程池,设置核心线程数、最大线程数、队列容量等参数,并演示如何提交任务。同时,需要强调在阿里巴巴开发规范中推荐手动创建线程池,而不是使用Executors,这点可能来自引用[3]中的最佳实践。 然后,讨论最佳实践,比如合理配置线程数、使用有界队列、处理未捕获异常、正确关闭线程池等。这些内容在引用[3]中有涉及,比如异常处理和分析的重要性,以及关闭线程池的方法。 此外,要注意线程池的任务拒绝策略,如AbortPolicy、CallerRunsPolicy等,并说明在不同场景下如何选择合适的策略。这部分可能需要结合引用[2]中提到的使用过程中遇到的坑。 最后,生成相关问题,可能包括线程池的参数配置、不同线程池类型的区别、如何监控线程池状态、常见的线程池问题排查等,确保问题与用户查询内容相关,并帮助深化理解。 需要确保回答结构清晰,分步骤说明,代码正确,并且引用正确的位置。例如,在提到线程池参数配置时,引用[3]中的最佳实践;在提到任务拒绝策略时,引用[2]中的实际应用经验。 现在需要将以上思考整理成中文回答,确保符合用户要求的格式,使用正确的LaTeX语法,并在适当的位置添加引用标识。</think>### 如何在Java使用线程池? #### 1. **线程池的作用与优势** - **资源复用**:避免频繁创建/销毁线程,提升性能[^2]。 - **控制并发**:通过核心线程数、最大线程数限制资源占用[^3]。 - **任务管理**:使用队列缓冲任务,支持拒绝策略处理过载[^1]。 #### 2. **创建线程池** Java推荐通过`ThreadPoolExecutor`手动配置参数(而非`Executors`工厂类,避免潜在风险)[^3]: ```java int corePoolSize = 5; // 核心线程数 int maxPoolSize = 10; // 最大线程数 long keepAliveTime = 60L; // 空闲线程存活时间(秒) BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(100); // 有界队列 ThreadPoolExecutor executor = new ThreadPoolExecutor( corePoolSize, maxPoolSize, keepAliveTime, TimeUnit.SECONDS, queue, new ThreadPoolExecutor.AbortPolicy() // 默认拒绝策略:直接抛出异常 ); ``` #### 3. **提交任务** - 使用`execute()`提交`Runnable`任务: ```java executor.execute(() -> { System.out.println("Task executed by " + Thread.currentThread().getName()); }); ``` - 使用`submit()`提交`Callable`任务(可获取返回值): ```java Future<String> future = executor.submit(() -> { return "Result from thread " + Thread.currentThread().getName(); }); System.out.println(future.get()); // 阻塞获取结果 ``` #### 4. **最佳实践** - **参数配置**: - CPU密集型任务:核心线程数 ≈ CPU核心数[^3]。 - I/O密集型任务:核心线程数可适当增加(如2倍CPU核心数)。 - 使用有界队列避免内存溢出[^3]。 - **异常处理**: ```java executor.setRejectedExecutionHandler((r, executor) -> { // 自定义拒绝策略,如记录日志或降级处理 }); // 任务内捕获异常 executor.execute(() -> { try { // 业务逻辑 } catch (Exception e) { // 记录异常 } }); ``` - **关闭线程池**: ```java executor.shutdown(); // 等待已提交任务完成 // executor.shutdownNow(); // 立即终止所有任务(慎用) ``` #### 5. **常用线程池类型** - **FixedThreadPool**:固定线程数,适用于负载较重的场景。 ```java ExecutorService fixedPool = Executors.newFixedThreadPool(5); ``` - **CachedThreadPool**:弹性线程数,适合短时异步任务[^1]。 - **ScheduledThreadPool**:支持定时/周期性任务。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值