1.请大ç¥å¸®çä¸ä¸..Caused by: java.lang.ClassCastException: org.quartz.simpl.SimpleThreadPool
2.TimeråScheduledThreadPoolExecutorçåºå«
3.Java高并发编程实战5,源码异步注解@Async自定义线程池
4.Spring框架中的源码线程池
5.Spring自带的线程池ThreadPoolTaskExecutor
请大ç¥å¸®çä¸ä¸..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提供了强大的线程管理功能,通过合理的配置和使用,可以显著提高应用的并发处理能力。了解并熟练使用这些配置和策略,将帮助开发者构建更高效、稳定的多线程应用。