Java多线程优化之线程池的使用方法

简介: Java多线程优化之线程池的使用方法

Java多线程优化之线程池

java标准库提供了ExecutorService接口表示线程池
创建这些线程池的方法都被封装到Executors这个类

一、FixedThreadPool

FixedThreadPool:线程数固定的线程池

public class ThreadPoolTest01 {
    public static void main(String[] args) {
        //创建一个线程数固定为6的线程池
        ExecutorService es = Executors.newFixedThreadPool(6);
        for (int i = 0; i < 6; i++) {
            es.submit(new Task01("start task" + i));
        }
        // 关闭线程池:
        es.shutdown();
    }

}
class Task01 implements Runnable{
    private final String name;

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

    @Override
    public void run() {
        System.out.println("start task " + name);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }
        System.out.println("end task " + name);
    }
}

运行后:

start task start task0
start task start task3
start task start task1
start task start task2
start task start task4
start task start task5
end task start task3
end task start task2
end task start task5
end task start task1
end task start task4
end task start task0

二、CachedThreadPool

CachedThreadPool:线程数根据任务动态调整的线程池

public class ThreadPoolTest02 {
    public static void main(String[] args) {
        ExecutorService es = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            es.submit(new Task02("start task" + i));
        }
        es.shutdown();
    }
}

class Task02 implements Runnable{
    private final String name;

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

    @Override
    public void run() {
        System.out.println("start task " + name);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }
        System.out.println("end task " + name);
    }
}

运行后:

start task start task0
start task start task1
start task start task2
start task start task3
start task start task4
end task start task1
end task start task0
end task start task3
end task start task4
end task start task2

如果想控制线程池的大小呢?首先看一下Executors.newCachedThreadPool()方法的源码:
MAX_VALUE = 0x7fffffff

/**
     * Creates a thread pool that creates new threads as needed, but
     * will reuse previously constructed threads when they are
     * available.  These pools will typically improve the performance
     * of programs that execute many short-lived asynchronous tasks.
     * Calls to {@code execute} will reuse previously constructed
     * threads if available. If no existing thread is available, a new
     * thread will be created and added to the pool. Threads that have
     * not been used for sixty seconds are terminated and removed from
     * the cache. Thus, a pool that remains idle for long enough will
     * not consume any resources. Note that pools with similar
     * properties but different details (for example, timeout parameters)
     * may be created using {@link ThreadPoolExecutor} constructors.
     *
     * @return the newly created thread pool
     */
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

可以这样实现:

int min = 5;
int max = 10;
ExecutorService es = new ThreadPoolExecutor(min, max,
        60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());

第一个参数min 表示这个线程池初始化了5个线程在里面工作
第二个参数max 表示如果5个线程不够用了,就会自动增加到最多10个线程
第三个参数60 结合第四个参数TimeUnit.SECONDS,表示经过60秒,多出来的线程还没有接到活儿,就会回收,最后保持池子里就5个
第四个参数TimeUnit.SECONDS 如上
第五个参数 new LinkedBlockingQueue() 用来放任务的集合

三、SingleThreadExecutor

SingleThreadExecutor:仅单线程执行的线程池
适用场景:任务需要定期反复执行

public class ThreadPoolTest03 {
    public static ScheduledExecutorService ses = Executors.newScheduledThreadPool(4);

    public static void main(String[] args) {
        //一秒后执行一次性任务
        ses.schedule(new Task03("one-time"), 1, TimeUnit.SECONDS);
        //2秒后开始执行定时任务,每3秒执行  
        //FixedRate是指任务总是以固定时间间隔触发,不管任务执行多长时间
        ses.scheduleAtFixedRate(new Task03("fixed-rate"), 2, 3, TimeUnit.SECONDS);
        //2秒后开始执行定时任务,以3秒为间隔执行 
        //FixedDelay是指,上一次任务执行完毕后,等待固定的时间间隔,再执行下一次任务
        ses.scheduleWithFixedDelay(new Task03("fixed-delay"),2,3,TimeUnit.SECONDS);
    }

}
class Task03 implements Runnable{
    private final String name;

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

    @Override
    public void run() {
        System.out.println("start task " + name);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }
        System.out.println("end task " + name);
    }
}

注意

线程池在程序执行完必须要关闭
1.调用shutdown()时,线程池的状态则立刻变成SHUTDOWN状态。此时,则不能再往线程池中添加任何任务,否则将会抛出RejectedExecutionException异常。
2.调用awaitTermination()则会等待指定的时间让线程池关闭。

目录
相关文章
|
1天前
|
缓存 Java
异步&线程池 线程池的七大参数 初始化线程的4种方式 【上篇】
这篇文章详细介绍了Java中线程的四种初始化方式,包括继承Thread类、实现Runnable接口、实现Callable接口与FutureTask结合使用,以及使用线程池。同时,还深入探讨了线程池的七大参数及其作用,解释了线程池的运行流程,并列举了四种常见的线程池类型。最后,阐述了在开发中使用线程池的原因,如降低资源消耗、提高响应速度和增强线程的可管理性。
异步&线程池 线程池的七大参数 初始化线程的4种方式 【上篇】
|
1天前
|
Java
java开启线程的四种方法
这篇文章介绍了Java中开启线程的四种方法,包括继承Thread类、实现Runnable接口、实现Callable接口和创建线程池,每种方法都提供了代码实现和测试结果。
java开启线程的四种方法
|
4天前
|
存储 缓存 安全
深度剖析Java HashMap:源码分析、线程安全与最佳实践
深度剖析Java HashMap:源码分析、线程安全与最佳实践
|
4天前
|
算法 安全 Java
深入解析Java多线程:源码级别的分析与实践
深入解析Java多线程:源码级别的分析与实践
|
3月前
|
设计模式 监控 Java
Java多线程基础-11:工厂模式及代码案例之线程池(一)
本文介绍了Java并发框架中的线程池工具,特别是`java.util.concurrent`包中的`Executors`和`ThreadPoolExecutor`类。线程池通过预先创建并管理一组线程,可以提高多线程任务的效率和响应速度,减少线程创建和销毁的开销。
69 2
|
3月前
|
Java 数据库
【Java多线程】对线程池的理解并模拟实现线程池
【Java多线程】对线程池的理解并模拟实现线程池
40 1
|
12天前
|
安全 算法 Java
17 Java多线程(线程创建+线程状态+线程安全+死锁+线程池+Lock接口+线程安全集合)(下)
17 Java多线程(线程创建+线程状态+线程安全+死锁+线程池+Lock接口+线程安全集合)
52 6
|
12天前
|
存储 安全 Java
17 Java多线程(线程创建+线程状态+线程安全+死锁+线程池+Lock接口+线程安全集合)(中)
17 Java多线程(线程创建+线程状态+线程安全+死锁+线程池+Lock接口+线程安全集合)
53 5
|
12天前
|
存储 安全 Java
17 Java多线程(线程创建+线程状态+线程安全+死锁+线程池+Lock接口+线程安全集合)(上)
17 Java多线程(线程创建+线程状态+线程安全+死锁+线程池+Lock接口+线程安全集合)
47 3
|
1月前
|
设计模式 存储 安全
Java面试题:设计一个线程安全的单例类并解释其内存占用情况?使用Java多线程工具类实现一个高效的线程池,并解释其背后的原理。结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
Java面试题:设计一个线程安全的单例类并解释其内存占用情况?使用Java多线程工具类实现一个高效的线程池,并解释其背后的原理。结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
35 1