【医院随访系统 源码】【flask 电影项目源码】【博客源码完整】simplethreadpool源码

来源:秦殇 源码

1.请大神帮看一下..Caused by: java.lang.ClassCastException: org.quartz.simpl.SimpleThreadPool
2.Timer和ScheduledThreadPoolExecutor的区别
3.Java高并发编程实战5,源码异步注解@Async自定义线程池
4.Spring框架中的源码线程池
5.Spring自带的线程池ThreadPoolTaskExecutor

simplethreadpool源码

请大神帮看一下..Caused by: java.lang.ClassCastException: org.quartz.simpl.SimpleThreadPool

       è²Œä¼¼æ˜¯çº¿ç¨‹æ± åˆå§‹åŒ–的问题

       ç±»åž‹è½¬æ¢é”™è¯¯ï¼Œä½ æ¢ä¸€ä¸ªæ–°ç‰ˆçš„quartz包试试

       ä½ é…ç½®äº†çº¿ç¨‹æ± æ–‡ä»¶äº†ä¹ˆï¼Ÿ

       SimpleThreadPool的属性文件

Timer和ScheduledThreadPoolExecutor的区别

       åœ¨å®žé™…应用中,有时候我们需要创建一些个延迟的、并具有周期性的任务,比如,我们希望当我们的程序启动后每隔1小时就去做一次日志记录。在JDK中提供了两种方法去创建延迟周期性任务。

       Timer

       Timer是java.util包下的一个类,在JDK1.3的时候被引入,Timer只是充当了一个执行者的角色,真正的任务逻辑是通过一个叫做TimerTask的抽象类完成的,TimerTask也是java.util包下面的类,它是一个实现了Runnable接口的抽象类,包含一个抽象方法run( )方法,需要我们自己去提供具体的业务实现。

       Timer类对象是通过其schedule方法执行TimerTask对象中定义的业务逻辑,并且schedule方法拥有多个重载方法提供不同的延迟与周期性服务。

       ä¸‹é¢æ˜¯åˆ©ç”¨Timer去创建的一个延时周期性任务

       import java.text.SimpleDateFormat;

       import java.util.Date;

       import java.util.Timer;

       import java.util.TimerTask;

       public class TestTimer {

        public static void main(String[] args) {

        String time = new SimpleDateFormat("HH:mm:ss").format(new Date());

        System.out.println("Start time : " + time);

        Timer timer = new Timer();

        TimerTask task = new TimerTask() {

        @Override

        public void run() {

        // TODO Auto-generated method stub

        String time = new SimpleDateFormat("HH:mm:ss").format(new Date());

        System.out.println("Now Time : " + time);

        }

        }; //end task

        timer.schedule(task, , );

        }

       }

       ç¨‹åºçš„输出:

       Start time : ::

       Now Time : ::

       Now Time : ::

       Now Time : ::

       Now Time : ::

       ScheduledThreadPoolExecutor

       åœ¨JDK1.5的时候在java.util.concurrent并发包下引入了ScheduledThreadPoolExecutor类,引入它的原因是因为Timer类创建的延迟周期性任务存在一些缺陷, ScheduledThreadPoolExecutor继承了ThreadPoolExecutor,并且实现了ScheduledExecutorService接口, ScheduledThreadPoolExecutor也是通过schedule方法执行Runnable任务的。

       æˆ‘们用 ScheduledThreadPoolExecutor来实现和上述Timer一样的功能

       import java.text.SimpleDateFormat;

       import java.util.Date;

       import java.util.concurrent.ScheduledThreadPoolExecutor;

       import java.util.concurrent.TimeUnit;

       public class TestScheduledThreadPoolExecutor {

        public static void main(String[] args) {

        String time = new SimpleDateFormat("HH:mm:ss").format(new Date());

        System.out.println("Start time : " + time);

        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(5); //创建5个执行线程

        Runnable runnable = new Runnable() {

        @Override

        public void run() {

        // TODO Auto-generated method stub

        String time = new SimpleDateFormat("HH:mm:ss").format(new Date());

        System.out.println("Now Time : " + time);

        }

        };

        executor.scheduleWithFixedDelay(runnable, 2, 3, TimeUnit.SECONDS);

        }

       }

       ç¨‹åºçš„输出:

       Start time : ::

       Now Time : ::

       Now Time : ::

       Now Time : ::

       Now Time : ::

       è¿™æ ·çœ‹æ¥Timer和 ScheduledThreadPoolExecutor好像没有声明差别,但是 ScheduledThreadPoolExecutor的引入正是由于Timer类存在的一些不足,并且在JDK1.5或更高版本中,几乎没有利用继续使用Timer类,下面说明Timer存在的一些缺点。

       å•çº¿ç¨‹

       Timer类是通过单线程来执行所有的TimerTask任务的,如果一个任务的执行过程非常耗时,将会导致其他任务的时效性出现问题。而 ScheduledThreadPoolExecutor是基于线程池的多线程执行任务,不会存在这样的问题。

       è¿™é‡Œæˆ‘们通过让Timer来执行两个TimerTask任务来说明,其中一个TimerTask的执行过程是耗时的,加入需要2秒。

       import java.text.SimpleDateFormat;

       import java.util.Date;

       import java.util.Timer;

       import java.util.TimerTask;

       public class SingleThreadTimer {

        public static void main(String[] args) {

        String time = new SimpleDateFormat("HH:mm:ss").format(new Date());

        System.out.println("Start time : " + time);

        Timer timer = new Timer();

        TimerTask task1 = new TimerTask() {

        @Override

        public void run() {

        // TODO Auto-generated method stub

        String time = new SimpleDateFormat("HH:mm:ss").format(new Date());

        System.out.println("Task1 time : " + time);

        }

        };

        TimerTask task2 = new TimerTask() {

        @Override

        public void run() {

        // TODO Auto-generated method stub

        try {

        Thread.sleep();

        } catch (InterruptedException e) {

        // TODO Auto-generated catch block

        e.printStackTrace();

        }

        String time = new SimpleDateFormat("HH:mm:ss").format(new Date());

        System.out.println("task2 time : " + time);

        }

        };

        timer.schedule(task1, , );

        timer.schedule(task2, , );

        }

       }

       è¿™é‡Œå®šä¹‰äº†ä¸¤ä¸ªä»»åŠ¡ï¼Œä»»åŠ¡1,程序启动2秒后每隔1秒运行一次,任务2,程序启动2秒后,每隔3秒运行1次,然后让Timer同时运行这两个任务

       ç¨‹åºçš„输出如下:

       Start time : ::

       Task1 time : ::

       task2 time : ::

       Task1 time : ::

       Task1 time : ::

       task2 time : ::

       Task1 time : ::

       Task1 time : ::

       task2 time : ::

       Task1 time : ::

       Task1 time : ::

       å¯ä»¥åˆ†æžï¼Œæ— è®ºæ˜¯ä»»åŠ¡1还是任务2都没有按照我们设定的预期进行运行,造成这个现象的原因就是Timer类是单线程的。

       Timer线程不捕获异常

       Timer类中是不捕获异常的,假如一个TimerTask中抛出未检查异常(P.S: java中异常分为两类:checked exception(检查异常)和unchecked exception(未检查异常),对于未检查异常也叫RuntimeException(运行时异常). ),Timer类将不会处理这个异常而产生无法预料的错误。这样一个任务抛出异常将会导致整个Timer中的任务都被取消,此时已安排但未执行的TimerTask也永远不会执行了,新的任务也不能被调度(所谓的“线程泄漏”现象)。

       ä¸‹é¢å°±å·²å¸¸è§çš„RuntimeException,ArrayIndexOutOfBoundsException数组越界异常,来演示这个缺点:

       import java.text.SimpleDateFormat;

       import java.util.Date;

       import java.util.Timer;

       import java.util.TimerTask;

       public class TestTimerTask {

        public static void main(String[] args) {

        System.out.println(new SimpleDateFormat("HH:mm:ss").format(new Date()));

        Timer timer = new Timer();

        TimerTask task1 = new TimerTask() {

        @Override

        public void run() {

        System.out.println("1: " + new SimpleDateFormat("HH:mm:ss").format(new Date()));

        }

        };

        TimerTask task2 = new TimerTask() {

        @Override

        public void run() {

        int[] arr = { 1,2,3,4,5};

        try {

        Thread.sleep();

        } catch (InterruptedException e) {

        e.printStackTrace();

        }

        int index = (int)(Math.random()*);

        System.out.println(arr[index]);

        System.out.println("2: " + new SimpleDateFormat("HH:mm:ss").format(new Date()));

        }

        };

        timer.schedule(task1, , );

        timer.schedule(task2, , );

        }

       }

       ç¨‹åºä¼šåœ¨è¿è¡Œè¿‡ç¨‹ä¸­æŠ›å‡ºæ•°ç»„越界异常,并且整个程序都会被终止,原来完好的任务1也被终止了。

       åŸºäºŽç»å¯¹æ—¶é—´

       Timer类的调度是基于绝对的时间的,而不是相对的时间,因此Timer类对系统时钟的变化是敏感的,举个例子,加入你希望任务1每个秒执行一次,某个时刻,你将系统时间提前了6秒,那么任务1就会在4秒后执行,而不是秒后。在 ScheduledThreadPoolExecutor,任务的调度是基于相对时间的,原因是它在任务的内部 存储了该任务距离下次调度还需要的时间(使用的是基于 System#nanoTime实现的相对时间 ,不会因为系统时间改变而改变,如距离下次执行还有秒,不会因为将系统时间调前6秒而变成4秒后执行)。

       åŸºäºŽä»¥ä¸Š3个弊端,在JDK1.5或以上版本中,我们几乎没有理由继续使用Timer类,ScheduledThreadPoolExecutor可以很好的去替代Timer类来完成延迟周期性任务。

Java高并发编程实战5,异步注解@Async自定义线程池

       @Async注解的源码作用是异步处理任务。

       在使用@Async时,源码如果不指定线程池的源码名称,默认线程池是源码医院随访系统 源码Spring默认的线程池SimpleAsyncTaskExecutor。

       默认线程池的源码配置如下:

       从最大线程数可以看出,在并发情况下,源码会无限制地创建线程。源码

       也可以通过yml重新配置:

       也可以自定义线程池,源码下面通过简单的源码代码来实现@Async自定义线程池。

       二、源码代码实例

       导入POM

       配置类AsyncTaskConfig

       UserController

       UserService

       UserServiceImpl

       三、源码为什么在文件内执行异步任务,源码还是源码flask 电影项目源码一个线程,没有实现@Async效果?

       在众多尝试中,找到了@Async失效的几个原因:

       四、配置中使用了ThreadPoolTaskExecutor和ThreadPoolExecutor,这两个有什么区别?

       ThreadPoolTaskExecutor是spring core包中的,而ThreadPoolExecutor是JDK中的JUC。

       1、initialize()

       查看ThreadPoolTaskExecutor的initialize()方法

       2、initializeExecutor抽象方法

       再查看initializeExecutor抽象方法的具体实现类,其中有一个就是ThreadPoolTaskExecutor类,查看它的initializeExecutor方法,使用的就是ThreadPoolExecutor。

       因此可以了解到ThreadPoolTaskExecutor是对ThreadPoolExecutor进行了封装。

       五、核心线程数

       配置文件中的博客源码完整线程池核心线程数为何配置为Runtime.getRuntime().availableProcessors()?

       获取的是CPU核心线程数,也就是计算资源。

       在实际中,需要对具体的线程池大小进行调整,可以通过压测及机器设备现状,进行调整大小。如果线程池太大,则会造成CPU不断的切换,对整个系统性能也不会有太大的提升,反而会导致系统缓慢。

       六、线程池执行流程

Spring框架中的线程池

       Spring框架中的线程池使用Java的ExecutorService接口实现,以优化并发任务执行和资源管理。以下是在Spring框架中使用线程池的基本步骤:

       1. **导入依赖**:确保项目包含了线程池所需依赖。通常,android ROM源码编译使用Spring Boot创建项目时,依赖会自动包含。

       2. **创建线程池**:可以通过配置文件或Java代码创建线程池。配置文件中,可在`application.properties`或`application.yml`中设置线程池属性。使用Java代码,通过`ThreadPoolTaskExecutor`或`ThreadPoolExecutor`创建对象。

       3. **注入线程池**:在代码中,通过依赖注入方式将线程池注入到需要使用异步任务执行或并发处理的类或方法中。

       4. **提交任务**:一旦注入线程池,即可使用它提交任务进行执行。

       5. **获取结果**:需要结果时,使用`submit()`方法提交任务,获取返回的源码 反码 补码-100`Future`对象来获取任务结果。

       6. **销毁线程池**:在Spring应用程序关闭时,确保销毁线程池以释放资源。

       ### 使用`@Async`注解执行异步任务

       在Spring中,`@Async`注解用于标记方法为异步执行,使其在调用时不阻塞主线程。具体步骤包括:

       1. **导入依赖**:确保项目包含了使用`@Async`注解所需的依赖。

       2. **启用异步支持**:在Spring配置中,启用异步支持。使用Java配置方式,在配置类上加上`@EnableAsync`注解;使用XML配置方式,可在XML配置文件中添加相关配置。

       3. **标记异步方法**:将`@Async`注解添加到希望异步执行的方法上。

       4. **配置线程池**:指定任务执行器名称。默认使用`SimpleAsyncTaskExecutor`,但可自定义线程池配置。

       5. **配置`SimpleAsyncTaskExecutor`**:通过创建`TaskExecutor`的bean并返回,设置线程池的并发限制、线程名前缀等属性。

       6. **配置`ThreadPoolTaskExecutor`**:提供更高级的线程池管理功能,包括线程池大小、存活时间、拒绝策略等,通过`set`方法进行配置。

       ### 异步方法执行

       - **调用**:在其他组件或类中直接调用带有`@Async`注解的异步方法。

       ### `@Async`实现原理

       `@Async`注解实现使用AOP、动态代理、Java反射、线程池、Runnable和Callable接口、Future接口等技术,通过这些技术的组合实现异步方法的调用和执行。具体实现涉及生成代理对象、任务执行器的选择和方法调用的封装。

       ### 选择任务执行器

       根据`@Async`注解配置选择任务执行器,Spring将根据配置选择相应的线程池或任务执行器,未指定时使用默认执行器。

       ### 总结

       在Spring框架中,通过合理利用线程池和`@Async`注解,可以有效地管理并发任务,提高应用性能和响应速度。根据具体需求和场景,选择合适的线程池配置和执行器,实现灵活、高效的异步任务处理。

Spring自带的线程池ThreadPoolTaskExecutor

       Spring默认线程池simpleAsyncTaskExecutor为开发者提供了异步处理功能,每次执行任务时重新启动一个新的线程。默认情况下,没有资源节流,允许控制并发线程的最大数量(concurrencyLimit)。虽然Spring推荐使用ThreadPoolTaskExecutor,但默认配置使用simpleAsyncTaskExecutor。

       Spring的线程池ThreadPoolTaskExecutor是对java.util.concurrent.ThreadPoolExecutor的封装,为开发者提供更灵活的线程管理。通过Spring提供的配置方式,可以轻松创建并管理线程池。

       配置ThreadPoolTaskExecutor通常在application.properties文件中进行,或使用@Configuration注解定义。通过在方法上添加@Async注解,方法将自动异步执行,并在启动类或配置类添加@EnableAsync注解以启用多线程调用。

       ThreadPoolTaskExecutor支持线程复用,控制线程数量,以优化多线程并发程序的性能。同时,配置拒绝策略(rejectedExectutionHandler)以处理超过最大线程数的情况,例如丢弃任务、记录错误或执行其他策略。

       拒绝策略的配置通常涉及七种策略类型,如AbortPolicy、DiscardPolicy、DiscardOldestPolicy等,开发者可根据需求选择合适策略。

       总的来说,Spring的ThreadPoolTaskExecutor提供了强大的线程管理功能,通过合理的配置和使用,可以显著提高应用的并发处理能力。了解并熟练使用这些配置和策略,将帮助开发者构建更高效、稳定的多线程应用。

文章所属分类:探索频道,点击进入>>