Java线程池初步学习

目录

一、什么是线程池

二、为什么要有线程池?还有什么池?

三、多线程学习:ExecutorServise接口

1、线程池的关闭

2、FixedThreadPool执行逻辑 

3、CachedThreadPool执行逻辑

四、ScheduledThreadPool线程池:周期性和定时性

1、定时性:schedule方法

2、周期性:scheduleAtFixedRate方法


一、什么是线程池

虽然启动一个新线程很方便,但是创建线程需要操作系统资源,比如说线程资源或者栈的空间。频繁地创建和销毁大量的线程会消耗大量时间。所以我们可以把很多小任务让一组线程来执行,而不是一个任务对应一个新线程。

其实我觉得池的概念可以理解为“共享单车”的存在。

简单来说,线程池内部维护了很多个线程,没有任务的时候,线程都处于“待机状态”。如果有新任务,就分一个空闲线程去执行。

二、为什么要有线程池?还有什么池?

先抛池的概念去手动创建、释放管理线程,相比于创建线程的空间开销,为觉得多线程的上下文切换开销、同步开销和时间开销才是需要考虑的。

池的概念往往都是为了化零散为批处理,为了复用减少创建销毁的开销。

除了线程池,我还见过缓冲池、数据池(常量池)和内存池。

三、多线程学习:ExecutorServise接口

ExecutorService是接口,其中提供的几个常用实现类有:

  • FixedThreadPool:线程数固定的线程池;
  • CachedThreadPool:线程数根据任务动态调整的线程池;
  • SingleThreadExecutor:仅单线程执行的线程池。

这些类的前面加个new就是创建相对应线程池的方法了,创建这些线程池的方法都在Executors类中: 

经典用法:

ExecutorServise executor = Executors.newFixedThreadPool(3); //固定线程数
//提交任务
executor.submit(task1);
executor.submit(task2);

1、线程池的关闭

shutdown():等待正在执行的任务完成后,再关闭

shutdownNow():立刻停止正在执行的任务

awaitTermination():等待指定的时间让线程池关闭

2、FixedThreadPool执行逻辑 

public class ThreadPool2 {
    public static void main(String[] args) {
        ExecutorService es = Executors.newFixedThreadPool(4);  // 固定大小线程池
        for (int i = 0; i < 6; i++) {
            es.submit(new Task("" + i));
        }
        es.shutdown();  // 关闭线程池
    }
}

class Task implements Runnable {
    private final String name;
    public Task(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 1
start task 2
start task 0
start task 3
end task 0
end task 2
end task 1
end task 3
start task 4
start task 5
end task 4
end task 5
*/

上面的代码我们一次性放入了6个任务,但是线程池只有固定4个任务。所以执行逻辑是:前四个任务同时执行,等有线程空闲后再继续执行接下来的

3、CachedThreadPool执行逻辑

这样的线程池可以根据任务数量调整线程池大小,所以6个任务可以一次性全部同时执行

如果我们想把线程池大小限制在4-10个动态范围,我们可以:

int min = 4;
int max = 10;
ExecutorService es = new ThreadPoolExecutor(min, max,
        60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());   //这部分都是源码照抄

四、ScheduledThreadPool线程池:周期性和定时性

ScheduledThreadPool是一个能够实现周期性和定时性任务的线程池。

ScheduledThreadPoolExecutor继承自ThreadPoolExecutor。Executor是一个大接口,用于显性创建线程: 

1、定时性:schedule方法

ScheduledExecutorServise接口中的方法schedule用于自动完成特定任务,其中的参数列表中可以设置线程的执行时间:

public class TestScheduledThreadPool {
    //格式化
    static SimpleDateFormat sim = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    //AtomicInteger用来计数
    static AtomicInteger number = new AtomicInteger();

    public static void main(String[] args) throws Exception {
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
        for (int i = 0; i < 3; i++){
            executorService.schedule(new Runnable(){
                @Override
                public void run(){
                    System.out.println("第" + number.incrementAndGet() + "周期线程运行当前时间【" + sim.format(new Date()) + "】");
                    try{
                        Thread.sleep(3000);
                    }catch(InterruptedException e){
                        e.printStackTrace();
                    }
                }
            },3L,TimeUnit.SECONDS);
        }
        System.out.println("主线程运行当前时间【" + sim.format(new Date()) + "】");
    }
}

/*
主线程运行当前时间【2022-06-08 18:38:03】
第1周期线程运行当前时间【2022-06-08 18:38:06】
第2周期线程运行当前时间【2022-06-08 18:38:06】
第3周期线程运行当前时间【2022-06-08 18:38:09】
*/

可以看到周期线程是在主线程时间3s后执行的因为周期线程上来就等待三秒(schedule)。由于核心线程只设置了2个,所以第三个任务一样需要等待3秒后,有了空闲线程才能执行。之后的3秒都是线程任务里设置的睡眠时间(sleep)。

2、周期性:scheduleAtFixedRate方法

scheduleAtFixedRate方法提供周期执行任务的操作。和schedule方法很类似,上述代码只需要将参数“3L”改为“3,5”,周期线程就会以2s的间隔执行下去:

更多方法可以参考此博客: 深入理解Java线程池:ScheduledThreadPoolExecutor | Idea Buffer

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

颜 然

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值