多线程之线程池

什么是线程池:

在Java中,池的设计都是为了提高资源的重用性和系统的性能,降低资源创建和销毁的开销。线程池达成的也是类似的效果。我们创建和销毁线程会消耗系统资源,即使线程是轻量级的进程但是仍然会造成不小负担。

  1. 厨房中的厨师就是线程: 想象一下,你的厨房里有一群厨师,每个厨师都是一个线程,负责烹饪不同的菜肴。
  2. 顾客点菜就是任务: 每当顾客来点菜,相当于有一个新的任务进入系统,需要厨师去做。
  3. 任务的处理速度: 假设每个菜肴需要一定的时间来烹饪。如果每次有顾客点菜都要招募一个新的厨师(创建新线程),那么会增加很多开销,比如为新厨师分配工作空间、准备厨具等,这就是线程创建和销毁的开销。
  4. 线程池的作用: 相反,如果你事先准备好一群厨师(线程池),当顾客点菜时,只需从这群厨师中选一个空闲的厨师来做即可,不需要再额外招募新的厨师(创建新线程)。
  5. 控制厨师数量: 另外,你可能会考虑到厨房的大小和工作效率,不会让太多的厨师同时在厨房里工作(控制线程数量),以免拥挤和混乱。

如果我们需要做饭直接叫没活干的厨师来做就行了,不用再去外面找一个厨师。就大大提升了效率。

java库中的线程池:

ThreadPoolExecutor类

我们经常使用的是ThreadPoolExecutor这个线程池的实现,可以写入核心线程数、最大线程数、线程存活时间等一些相关的配置来调整线程池的状态。

面试题:线程池的的构造方法参数。

这里一共有七个参数:

  1. corePoolSize和maximunPoolSize:表示核心线程数最大线程数,如果任务没有那么繁忙,通过核心线程就能解决,如果比较繁忙的话就得调用临时线程,核心线程+临时线程<=最大线程数。
  2. keepAliveTime和unit:    表示最长空闲时间设置该空闲时间的单位。 线程在一定时间内不执行,系统就会自动回收。
  3. workQueue:是一个任务队列,线程提供submit方法 ,其他线程将任务提交给线程池,也就是将任务交到这个任务队列。
  4. threadFactory:是线程工厂,也就是创建线程的地方,
  5. handler:任务量超出负荷拒绝策略,

Executors类:

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

public class Demo20 {
    public static void main(String[] args) {

        ExecutorService service=Executors.newFixedThreadPool(4);
        service.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello");
            }
        });
    }
}

通过submit方法将重写run方法并且执行。

创建线程有两种方式:

1.通过Executors类:

  1.  如果需要一个简单的线程池来执行任务,而且不需要对线程池的参数进行配置,那么可以使用 Executors 提供的工厂方法
  2.  Executors 提供了许多预定义的线程池类型,使用这些工厂方法可以更加方便地创建标准类型的线程池,而无需手动配置线程池的参数。

自定义线程池的情况:

  1. 实际上自定义线程就是根据自己的需要来进行定义,能够满足更多需求,但是不走也相对繁琐。

自己实现一个线程池

我们将会自己实现一个线程池

线程池包括的内容:

  1. 核心操作为 submit,将任务加入到线程池中
  2. 要有n个工作线程,使用 Runnable 描述一个任务
  3. 使用一个 BlockingQueue 组织所有的任务
  4. 每个工作线程要做的事情:不停的从 BlockingQueue 中取任务执行
  5. 指定一下线程池中的最大线程数 maxWorkerCount, 当前线程数达到这个最大值时,就不在新增线程了
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class MyThreadPool {
    private BlockingQueue<Runnable> blockingQueue=new ArrayBlockingQueue<>(1000);


    public void submit(Runnable runnable) throws InterruptedException {
        blockingQueue.put(runnable);

    }

    public MyThreadPool(int n) {
        for (int i = 0; i <n ; i++) {
            Thread thread=new Thread(()->{
                try {
                    Runnable runnable = blockingQueue.take();
                    runnable.run();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }


            });
            thread.start();
        }
    }
}

public class Demo21 {
    public static void main(String[] args) throws InterruptedException {
        MyThreadPool myThreadPool=new MyThreadPool(129);
        for (int i = 0; i <1000 ; i++) {
            int id=i;
            myThreadPool.submit(new Runnable() {

                @Override
                public void run() {
                    System.out.println("数字"+id);
                }
            });

        }
    }

}
public class Demo21 {
    public static void main(String[] args) throws InterruptedException {
        MyThreadPool myThreadPool=new MyThreadPool(129);
        for (int i = 0; i <1000 ; i++) {
            int id=i;
            myThreadPool.submit(new Runnable() {

                @Override
                public void run() {
                    System.out.println("数字"+id);
                }
            });

        }
    }

}

这里有一个小知识点就是变量捕获的问题,所有我们得用 一个id来捕获i。

对于日常开发环境来说,我们常常使用官方提供的线程池就可以了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值