|
| 1 | +#分析 |
| 2 | + |
| 3 | +在Spring中,通过任务执行器,也就是TaskExecutor来实现多线程和并发编程。 |
| 4 | + |
| 5 | +使用ThreadPoolTaskExecutor可实现一个基于线程池的TaskExecutor。 |
| 6 | +而实际开发中任务一般是非阻碍的,也就是非异步的,所以我们要在配置类中通过@EnableAsync开启对异步任务的支持,并通过在实际执行的Bean的方法中使用@Async注解来声明其是一个异步任务。 |
| 7 | + |
| 8 | + |
| 9 | +进行本示例的演示,需要先配置好Maven和Spring哦、 |
| 10 | +见: |
| 11 | +<a href="http://blog.csdn.net/qq_26525215/article/details/53010442" target='_blank'>【Spring】基于IntelliJ IDEA搭建Maven</a> |
| 12 | + |
| 13 | +#示例 |
| 14 | + |
| 15 | +##配置类 |
| 16 | + |
| 17 | +首先看一下配置类。 |
| 18 | +现在全部使用Java配置哦,不用xml了。 |
| 19 | + |
| 20 | +``` |
| 21 | +package cn.hncu.p3.p2_TaskExecutor; |
| 22 | + |
| 23 | +import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; |
| 24 | +import org.springframework.context.annotation.ComponentScan; |
| 25 | +import org.springframework.context.annotation.Configuration; |
| 26 | +import org.springframework.scheduling.annotation.AsyncConfigurer; |
| 27 | +import org.springframework.scheduling.annotation.EnableAsync; |
| 28 | +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; |
| 29 | + |
| 30 | +import java.util.concurrent.Executor; |
| 31 | + |
| 32 | +/** |
| 33 | + * Created with IntelliJ IDEA. |
| 34 | + * User: 陈浩翔. |
| 35 | + * Date: 2016年11月18日. |
| 36 | + * Time: 上午 9:35. |
| 37 | + * Explain:配置类 |
| 38 | + */ |
| 39 | +@Configuration |
| 40 | +@ComponentScan("cn.hncu.p3.p2_TaskExecutor") |
| 41 | +@EnableAsync //利用@EnableAsync注解开启异步任务支持 |
| 42 | +public class TaskExecutorConfig implements AsyncConfigurer{ |
| 43 | + //配置类实现AsyncConfigurer接口并重写getAsyncExcutor方法,并返回一个ThreadPoolTaskExevutor |
| 44 | + //这样我们就获得了一个基于线程池的TaskExecutor |
| 45 | + @Override |
| 46 | + public Executor getAsyncExecutor() { |
| 47 | + ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); |
| 48 | + taskExecutor.setCorePoolSize(5);//线程池维护线程的最少数量 |
| 49 | + taskExecutor.setMaxPoolSize(10);//线程池维护线程的最大数量 |
| 50 | + taskExecutor.setQueueCapacity(25);//线程池所使用的缓冲队列 |
| 51 | + taskExecutor.initialize(); |
| 52 | + return taskExecutor; |
| 53 | + } |
| 54 | + |
| 55 | + @Override |
| 56 | + public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { |
| 57 | + return null; |
| 58 | + } |
| 59 | +} |
| 60 | + |
| 61 | +``` |
| 62 | + |
| 63 | + |
| 64 | +##任务执行类 |
| 65 | + |
| 66 | +也就是实际运行的,需要异步执行的类 |
| 67 | + |
| 68 | +``` |
| 69 | +package cn.hncu.p3.p2_TaskExecutor; |
| 70 | + |
| 71 | +import org.springframework.scheduling.annotation.Async; |
| 72 | +import org.springframework.stereotype.Service; |
| 73 | + |
| 74 | +/** |
| 75 | + * Created with IntelliJ IDEA. |
| 76 | + * User: 陈浩翔. |
| 77 | + * Date: 2016年11月18日. |
| 78 | + * Time: 上午 10:57. |
| 79 | + * Explain:任务执行类 |
| 80 | + */ |
| 81 | +@Service |
| 82 | +public class AsyncTaskService { |
| 83 | + |
| 84 | + @Async |
| 85 | + //通过@Async注解表明该方法是个异步方法,如果注解在类级别,则表明该类所有的方法都是异步方法。 |
| 86 | + // 而这里的方法自动被注入使用ThreadPoolTaskExecutor作为TaskExecutor |
| 87 | + public void executeAsyncTask(Integer i){ |
| 88 | + System.out.println("executeAsyncTask:"+i); |
| 89 | + } |
| 90 | + |
| 91 | + @Async |
| 92 | + public void executeAsyncTaskPlus(Integer i){ |
| 93 | + System.out.println("executeAsyncTaskPlus:"+i); |
| 94 | + } |
| 95 | + |
| 96 | +} |
| 97 | + |
| 98 | +``` |
| 99 | + |
| 100 | +##运行类 |
| 101 | + |
| 102 | +为了测试而写的运行调用方法的类 |
| 103 | + |
| 104 | +``` |
| 105 | +package cn.hncu.p3.p2_TaskExecutor; |
| 106 | + |
| 107 | +import org.springframework.context.annotation.AnnotationConfigApplicationContext; |
| 108 | + |
| 109 | +/** |
| 110 | + * Created with IntelliJ IDEA. |
| 111 | + * User: 陈浩翔. |
| 112 | + * Date: 2016年11月18日. |
| 113 | + * Time: 上午 11:04. |
| 114 | + * Explain:运行类 |
| 115 | + */ |
| 116 | +public class Main { |
| 117 | + public static void main(String[] args) { |
| 118 | + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TaskExecutorConfig.class); |
| 119 | + |
| 120 | + AsyncTaskService asyncTaskService = context.getBean(AsyncTaskService.class); |
| 121 | + for(int i=0;i<10;i++){ |
| 122 | + asyncTaskService.executeAsyncTaskPlus(i); |
| 123 | + asyncTaskService.executeAsyncTask(i+1); |
| 124 | + } |
| 125 | + context.close(); |
| 126 | + |
| 127 | + } |
| 128 | + |
| 129 | +} |
| 130 | + |
| 131 | +``` |
| 132 | + |
| 133 | +#运行结果 |
| 134 | + |
| 135 | + |
| 136 | +运行结果长了一点,所以只传了这么一点。 |
| 137 | +但是已经能够看出了,假如是原来那样的,是异步执行,那么肯定偶数行的输出比前一个奇数行的输出是大1的。 |
| 138 | + |
| 139 | +结果不是那样,它们不是异步进行的,在这里由一个主线程(main线程)。 |
| 140 | +for循环里面,每运行一行调用方法的,就会开一个线程。 |
| 141 | +也就是说,你每次的运行结果可能会不一样! |
| 142 | +所以,如果你的运行结果和我的不一样,不要慌哦。 |
0 commit comments