Java多线程~什么是线程池?如何创建线程池?你可以自己实现一个线程池吗?

目录

什么是线程池?

如何创建线程池?

普通创建

快捷创建

手动实现一个线程池


什么是线程池?

线程池是多线程案例中非常重要的一个部分,线程池的使用可以很好的减少每次启动、销毁线程的损耗.

在之前的学习中,接触过字符串常量池以及数据库连接池,根据之前的认识,池的作用就是缓存。

线程池,即初始化(new线程池对象的时候)就创建了一定数量的线程,这些创建的线程不断地从阻塞队列中取任务,相当于是消费者。其他线程(生产者)只需要不断提交任务到线程池中。

举个例子来解释线程池

线程池就相当于是一个快递公司,公司开始创建时有2个正式员工(即new线程池对象池创建的线程数),阻塞队列就是快递公司的仓库,这两个正式员工不断地从仓库中取出快递去送,送完之后再回来取其他快递去送,相当于整个过程中一直这两个正式员工一直存在,不能辞退(即这两个线程不能销毁,核心线程),这样就有效的减少了每次启动、销毁线程的损耗。

线程池的优势:线程的创建和销毁都是有一定的代价(性能的损耗),使用线程池就可以重复使用线程来执行多组任务(类似于缓存,起到线程复用的目的).

如何创建线程池?

普通创建

Java api文档中的构造方法

· corePoolSize:核心线程数,即newThreadPollExecutor对象时初始化创建的线程数

· maximumPoolSIze:线程池最大线程数(核心线程以及临时线程)

· keepAliveTime:临时线程允许的空闲时间

· unit:keepAliveTime的时间单位

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPoolExecutorDemo {
    public static void main(String[] args) {
        //创建一个线程池: 开了一个快递公司
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                5,
                10,
                60,
                TimeUnit.SECONDS,
                //一般不使用无边界的阻塞队列,因为内存有限
                new ArrayBlockingQueue<>(10000),
                //拒绝策略: 一般最多使用CallerRunsPolicy,或自己实现
                new ThreadPoolExecutor.CallerRunsPolicy()
        );
        pool.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello");
            }
        });
    }
}

快捷创建

· newFixedThreadPool:创建固定线程数的线程池

· newSingleThreadExecutor:创建只包含单个线程的线程池

· newCachedThreadPool:创建线程数目动态增长的线程池

· newScheduledThreadPool:计划任务的线程池,相当于进阶版的定时器

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExecutorServiceDemo {
    public static void main(String[] args) {
        //固定大小的线程池
        ExecutorService fixed = Executors.newFixedThreadPool(4);
        //单线程池
        ExecutorService single = Executors.newSingleThreadExecutor();
        //缓存的线程池
        ExecutorService cached = Executors.newCachedThreadPool();
        //计划任务的线程池
        ExecutorService scheduled = Executors.newScheduledThreadPool(10);
    }
}

手动实现一个线程池

在自己实现的线程池中具体包含如下内容:

· 线程池的核心操作为execute,将任务加入线程池中

· 使用阻塞队列来组织所有的任务(使用的是底层为数组的阻塞队列)

· 在创建线程池时,需要初始化核心线程的数目以及阻塞队列的容量

· 利用for循环来使初始化的核心线程不断地从阻塞队列中取任务,如果阻塞队列为空就等待

具体实现代码如下

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

/**
 * Created with IntelliJ IDEA.
 * Description: 自己模拟实现线程池
 * User: Li_yizYa
 * Date: 2022—05—27
 * Time: 23:48
 */
public class MyThreadPool {
    //线程数: 员工的数量
    private int count;
    //阻塞队列: 仓库
    private BlockingQueue<Runnable> queue;
    public MyThreadPool(int count, int capacity) {
        this.count = count;
        queue = new ArrayBlockingQueue<>(capacity);
        //线程池创建,就创建线程来不断取任务并执行
        for (int i = 0; i < count; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    //不停地从仓库中取任务: 如果取不到就等待
                    while(true) {
                        try {
                            Runnable task = queue.take();
                            task.run();//执行任务
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();
        }
    }
    //提交任务
    public void execute(Runnable task) {
        try {
            queue.put(task);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Li_yizYa

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

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

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

打赏作者

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

抵扣说明:

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

余额充值