作者:chszs,转载需注明。
本文提供了三个Spring多线程开发的例子,由浅入深,由于例子一目了然,所以并未做过多的解释。诸位一看便知。
前提条件:
1)在Eclipse创建一个Java项目,我取名为SpringThreadDemo。
2)项目所需的JAR包如图所示:
下面开始。
注:项目源码已经托管到GitHub,地址:https://github.com/chszs/SpringThreadDemo
例子1:Spring结合Java线程。
通过继承Thread创建一个简单的Java线程,然后使用@Component让Spring容器管理此线程,Bean的范围必须是prototype,因此每个请求都会返回一个新实例,运行每个单独的线程。
PrintThread.java
1. package com.chszs.thread;
2.
3. import org.springframework.stereotype.Component;
4. import org.springframework.context.annotation.Scope;
5.
6. @Component
7. @Scope("prototype")
8. public class PrintThread extends Thread{
9. @Override
10. public void run(){
11. " is running.");
12. try{
13. 5000);
14. catch(InterruptedException e){
15. e.printStackTrace();
16. }
17. " is running again.");
18. }
19. }
AppConfig.java
1. package com.chszs.config;
2.
3. import org.springframework.context.annotation.ComponentScan;
4. import org.springframework.context.annotation.Configuration;
5.
6. @Configuration
7. @ComponentScan(basePackages="com.chszs.thread")
8. public class AppConfig {
9. }
App.java
1. package com.chszs;
2. import org.springframework.context.ApplicationContext;
3. import org.springframework.context.annotation.AnnotationConfigApplicationContext;
4.
5. import com.chszs.config.AppConfig;
6. import com.chszs.thread.PrintThread;
7.
8. public class App {
9. public static void main(String[] args){
10. ApplicationContext ctx =
11. new AnnotationConfigApplicationContext(AppConfig.class);
12. "printThread");
13. "Thread 1");
14.
15. "printThread");
16. "Thread 2");
17.
18. "printThread");
19. "Thread 3");
20.
21. "printThread");
22. "Thread 4");
23.
24. "printThread");
25. "Thread 5");
26.
27. printThread1.start();
28. printThread2.start();
29. printThread3.start();
30. printThread4.start();
31. printThread5.start();
32. }
33. }
输出:
Thread 1 is running.
Thread 2 is running.
Thread 4 is running.
Thread 5 is running.
Thread 3 is running.
Thread 2 is running again.
Thread 1 is running again.
Thread 5 is running again.
Thread 4 is running again.
Thread 3 is running again.
例子2:Spring线程池结合非Spring托管Bean。
使用Spring的ThreadPoolTaskExecutor类创建一个线程池。执行线程无需受Spring容器的管理。
PrintTask.java
1. package com.chszs.thread;
2.
3. public class PrintTask implements Runnable{
4. String name;
5. public PrintTask(String name){
6. this.name = name;
7. }
8. @Override
9. public void run() {
10. " is running.");
11. try{
12. 5000);
13. catch(InterruptedException e){
14. e.printStackTrace();
15. }
16. " is running again.");
17. }
18.
19. }
Spring-Config.xml
1. <beans xmlns="http://www.springframework.org/schema/beans"
2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3. xmlns:context="http://www.springframework.org/schema/context"
4. xsi:schemaLocation="http://www.springframework.org/schema/beans
5. http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
6. http://www.springframework.org/schema/context
7. >
8.
9. <bean id="taskExecutor"
10. class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
11. <property name="corePoolSize" value="5" />
12. <property name="maxPoolSize" value="10" />
13. <property name="WaitForTasksToCompleteOnShutdown" value="true" />
14. </bean>
15. </beans>
注意这个Spring配置文件的位置,如图所示:
App1.java
1. package com.chszs;
2.
3. import org.springframework.context.ApplicationContext;
4. import org.springframework.context.support.ClassPathXmlApplicationContext;
5. import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
6.
7. import com.chszs.thread.PrintTask;
8.
9. public class App1 {
10.
11. public static void main(String[] args) {
12. ApplicationContext ctx =
13. new ClassPathXmlApplicationContext("resources/Spring-Config.xml");
14. ThreadPoolTaskExecutor taskExecutor =
15. "taskExecutor");
16. new PrintTask("Thread 1"));
17. new PrintTask("Thread 2"));
18. new PrintTask("Thread 3"));
19. new PrintTask("Thread 4"));
20. new PrintTask("Thread 5"));
21. // 检查活动的线程,如果活动线程数为0则关闭线程池
22. for(;;){
23. int count = taskExecutor.getActiveCount();
24. "Active Threads : " + count);
25. try{
26. 1000);
27. catch(InterruptedException e){
28. e.printStackTrace();
29. }
30. if(count==0){
31. taskExecutor.shutdown();
32. break;
33. }
34. }
35. }
36.
37. }
输出:
Thread 1 is running.
Thread 2 is running.
Thread 3 is running.
Thread 4 is running.
Active Threads : 4
Thread 5 is running.
Active Threads : 5
Active Threads : 5
Active Threads : 5
Active Threads : 5
Active Threads : 5
Thread 4 is running again.
Thread 2 is running again.
Thread 3 is running again.
Thread 1 is running again.
Thread 5 is running again.
Active Threads : 0
作者:chszs,转载需注明。
例子3:Spring线程池结合Spring托管Bean。
本例仍然使用ThreadPoolTaskExecutor类,并使用@Component注释声明Spring的托管Bean。
下面的例子PrintTask2是Spring的托管Bean,使用@Autowired注释简化代码。
PrintTask2.java
1. package com.chszs.thread;
2.
3. import org.springframework.context.annotation.Scope;
4. import org.springframework.stereotype.Component;
5.
6. @Component
7. @Scope("prototype")
8. public class PrintTask2 implements Runnable {
9. String name;
10.
11. public void setName(String name) {
12. this.name = name;
13. }
14.
15. @Override
16. public void run(){
17. " is running.");
18. try{
19. 5000);
20. catch(InterruptedException e){
21. e.printStackTrace();
22. }
23. " is running again.");
24. }
25. }
AppConfig.java
1. package com.chszs.config;
2.
3. import org.springframework.context.annotation.Bean;
4. import org.springframework.context.annotation.ComponentScan;
5. import org.springframework.context.annotation.Configuration;
6. import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
7.
8. @Configuration
9. @ComponentScan(basePackages="com.chszs.thread")
10. public class AppConfig {
11. @Bean
12. public ThreadPoolTaskExecutor taskExecutor(){
13. new ThreadPoolTaskExecutor();
14. 5);
15. 10);
16. true);
17. return pool;
18. }
19. }
App2.java
1. package com.chszs;
2.
3. import org.springframework.context.ApplicationContext;
4. import org.springframework.context.annotation.AnnotationConfigApplicationContext;
5. import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
6.
7. import com.chszs.config.AppConfig;
8. import com.chszs.thread.PrintTask2;
9.
10. public class App2 {
11. public static void main(String[] args) {
12. ApplicationContext ctx =
13. new AnnotationConfigApplicationContext(AppConfig.class);
14. ThreadPoolTaskExecutor taskExecutor =
15. "taskExecutor");
16.
17. "printTask2");
18. "Thread 1");
19. taskExecutor.execute(printTask1);
20.
21. "printTask2");
22. "Thread 2");
23. taskExecutor.execute(printTask2);
24.
25. "printTask2");
26. "Thread 3");
27. taskExecutor.execute(printTask3);
28.
29. for(;;){
30. int count = taskExecutor.getActiveCount();
31. "Active Threads : " + count);
32. try{
33. 1000);
34. catch(InterruptedException e){
35. e.printStackTrace();
36. }
37. if(count==0){
38. taskExecutor.shutdown();
39. break;
40. }
41. }
42. }
43.
44. }
输出:
Thread 1 is running.
Thread 2 is running.
Active Threads : 2
Thread 3 is running.
Active Threads : 3
Active Threads : 3
Active Threads : 3
Active Threads : 3
Thread 1 is running again.
Thread 2 is running again.
Thread 3 is running again.
Active Threads : 1
Active Threads : 0
从这三个简单的实例中,你是不是发现了Spring框架在多线程方面的强大之处!!