线程池(ExecutorService)

本文探讨了线程池的创建、优化以及构造方法的重载问题,介绍了使用JavaExecutorService创建线程池的方法,并通过生产者消费者模型实现任务分配。同时,讨论了线程池的执行流程和不同的拒绝策略。
摘要由CSDN通过智能技术生成

线程的存在就是因为进程再创建和销毁的时候申请和释放内存资源比较低效。线程创建后就能共享内存资源不用重复申请新的资源。

但如果线程创建的速率变得频繁,此时线程的开销也不能忽略!

此时就可以使用线程池优化这里的速度!

创建线程,是要在操作系统的内核中完成的。涉及到用户态->内核态的切换操作。这个操作有一定的开销。

线程池就是创建很多线程,当需要执行任务的时候,就不需要创建线程了,直接从池子里取个现成的。用完了也不需要释放线程,直接还回线程池中。 

此处创建线程池并没有像正常创建实例一样new,而是通过另外Executors类的静态方法newCachedThreadPool来完成。这种创建实例的方式叫工厂模式

构造实例时,主要是使用构造方法new.

而new的过程中,需要调用构造方法。有时候希望类提供多种构造实例的方法,就需要重载构造方法,来实现不同的版本的对象创建。但重载要求参数个数/类型不同,就存在一定的限制。

像此处的两个版本的构造方法就无法重载。

解决这个问题,可以用普通方法代替构造方法。使用普通方法,在里面构造出Point对象。

一、标准库的线程池

由于构造方法,方法名必须和类名相同,所以只能通过重载来完成,换成普通方法,直接通过方法名来完成,这样也不用考虑重载问题了。

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

public class Demo26 {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newCachedThreadPool();
        pool.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("这是任务");
            }
        });
    }
}

这里使用submit方法,把任务交给线程池就行。

二、实现线程池

线程池中,需要把N个任务分配给M个线程,这需要生产者消费者模型。

先创建一个阻塞队列,每个被提交的任务,都被放到阻塞队列中。然后建立M个线程取队列元素,如果队列空了,M个线程阻塞等待。

如果队列不为空,每个线程取任务,执行任务,再取下一个.....直至队空,线程阻塞。

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

class MyThreadPool {
    private BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();

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

    public  MyThreadPool(int m) {
        //在构造方法中,创建出M个线程,负责完成工作
        for (int i = 0; i < m; i++) {
            Thread t = new Thread(() -> {
                while (true) {
                    try {
                        Runnable runnable = queue.take();
                        runnable.run();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            t.start();
        }
    }
}
public class Demo27 {
    public static void main(String[] args) throws InterruptedException {
        MyThreadPool pool = new MyThreadPool(10);
        for (int i = 0; i < 1000; i++) {
            int taskId = i;
            pool.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("执行任务:" + taskId + "当前线程:" + Thread.currentThread().getName());
                }
            });
        }
    }
}

三、线程池的执行流程和拒绝策略:

线程池的执行流程:

(1)先判断当前线程数是否大于核心线程数,如果结果为true,则新建线程并执行任务

(2)如果结果为true,则判断任务队列是否已满,如果结果为fasle,就把任务添加到任务队列中等待线程执行

(3)如果结果为true,则判断当前线程数量是否超过最大线程数,如果结果为false,则新建线程执行次任务

(4)如果结果为true,就执行拒绝策略。

拒绝策略:

AbortPoliy:中止策略,线程池会抛出异常并中止执行此次任务

CallerRunPolicy:把任务交给添加此次任务main线程来执行

DiscardPolicy:忽略新任务,先执行旧任务

DiscardOldestPolicy:忽略最早的任务,执行新加入的任务

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java中,可以使用配置类来配置Executor线程池。其中,常用的实现类是`ExecutorService`和`ThreadPoolTaskExecutor`。 首先,需要创建一个配置类,可以命名为`ThreadPoolConfig`或者其他你喜欢的名称。在这个类中,你需要使用`@Configuration`注解来标识它是一个配置类,并且使用`@EnableAsync`注解来启用异步执行。 接下来,你需要定义一个`ExecutorService`或`ThreadPoolTaskExecutor` Bean,并使用`@Bean`注解将其标识为一个Bean。你可以根据项目的需求来选择使用哪个实现类。 如果选择使用`ExecutorService`,可以按照以下方式配置: ```java @Configuration @EnableAsync public class ThreadPoolConfig { @Bean public ExecutorService executorService() { return Executors.newFixedThreadPool(10); // 配置线程池的大小 } } ``` 如果选择使用`ThreadPoolTaskExecutor`,可以按照以下方式配置: ```java @Configuration @EnableAsync public class ThreadPoolConfig { @Bean public ThreadPoolTaskExecutor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(10); // 设置核心线程数 executor.setMaxPoolSize(20); // 设置最大线程数 executor.setQueueCapacity(30); // 设置队列容量 executor.setThreadNamePrefix("my-executor-"); // 设置线程名称前缀 executor.initialize(); // 初始化 return executor; } } ``` 在上述配置中,你可以根据实际需求来设置线程池的大小、队列容量等参数。通过这种方式,你就可以在应用程序中注入`ExecutorService`或`ThreadPoolTaskExecutor`,并使用它来执行异步任务。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值