查看: 8191|回复: 4

[精华] Spring线程池开发实战

[复制链接]
论坛徽章:
63
2010广州亚运会纪念徽章:台球
日期:2010-10-18 12:43:48茶鸡蛋
日期:2013-01-09 10:59:002013年新春福章
日期:2013-02-25 14:51:24奥运会纪念徽章:帆船
日期:2013-04-02 17:07:052013年新春福章
日期:2013-04-08 17:42:48奥运纪念徽章
日期:2013-07-18 13:55:12优秀写手
日期:2013-12-18 09:29:10马上有车
日期:2014-03-20 16:13:24马上有房
日期:2014-03-20 16:14:11马上有钱
日期:2014-03-20 16:14:11
发表于 2012-11-23 23:14 | 显示全部楼层 |阅读模式
本帖最后由 chszs 于 2012-11-23 23:15 编辑

《Spring线程池开发实战》

【版权声明】本文属于原创,版权归作者chszs所有,使用源码无任何限制,但转载文章需经作者同意。
本文提供了三个Spring多线程开发的例子,由浅入深,由于例子一目了然,所以并未做过多的解释。诸位一看便知。

前提条件:
1)在Eclipse创建一个Java项目,我取名为SpringThreadDemo。
2)项目所需的JAR包如图所示:
图片1.jpg
下面开始。
注:项目源码已经托管到GitHub,地址:https://github.com/chszs/SpringThreadDemo

例子1:Spring结合Java线程。
通过继承Thread创建一个简单的Java线程,然后使用@Component让Spring容器管理此线程,Bean的范围必须是prototype,因此每个请求都会返回一个新实例,运行每个单独的线程。
PrintThread.java
  1. package com.chszs.thread;

  2. import org.springframework.stereotype.Component;
  3. import org.springframework.context.annotation.Scope;

  4. @Component
  5. @Scope("prototype")
  6. public class PrintThread extends Thread{
  7.         @Override
  8.         public void run(){
  9.                 System.out.println(getName() + " is running.");
  10.                 try{
  11.                         Thread.sleep(5000);
  12.                 }catch(InterruptedException e){
  13.                         e.printStackTrace();
  14.                 }
  15.                 System.out.println(getName() + " is running again.");
  16.         }
  17. }
复制代码
AppConfig.java
  1. package com.chszs.config;

  2. import org.springframework.context.annotation.ComponentScan;
  3. import org.springframework.context.annotation.Configuration;

  4. @Configuration
  5. @ComponentScan(basePackages="com.chszs.thread")
  6. public class AppConfig {
  7. }
复制代码
App.java
  1. package com.chszs;
  2. import org.springframework.context.ApplicationContext;
  3. import org.springframework.context.annotation.AnnotationConfigApplicationContext;

  4. import com.chszs.config.AppConfig;
  5. import com.chszs.thread.PrintThread;

  6. public class App {
  7.         public static void main(String[] args){
  8.                 ApplicationContext ctx =
  9.             new AnnotationConfigApplicationContext(AppConfig.class);
  10.                 PrintThread printThread1 = (PrintThread)ctx.getBean("printThread");
  11.                 printThread1.setName("Thread 1");
  12.                
  13.                 PrintThread printThread2 = (PrintThread)ctx.getBean("printThread");
  14.                 printThread2.setName("Thread 2");
  15.                
  16.                 PrintThread printThread3 = (PrintThread)ctx.getBean("printThread");
  17.                 printThread3.setName("Thread 3");
  18.                
  19.                 PrintThread printThread4 = (PrintThread)ctx.getBean("printThread");
  20.                 printThread4.setName("Thread 4");
  21.                
  22.                 PrintThread printThread5 = (PrintThread)ctx.getBean("printThread");
  23.                 printThread5.setName("Thread 5");
  24.                
  25.                 printThread1.start();
  26.                 printThread2.start();
  27.                 printThread3.start();
  28.                 printThread4.start();
  29.                 printThread5.start();
  30.         }
  31. }
复制代码
输出:
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. public class PrintTask implements Runnable{
  3.         String name;
  4.         public PrintTask(String name){
  5.                 this.name = name;
  6.         }
  7.         @Override
  8.         public void run() {
  9.                 System.out.println(name + " is running.");
  10.                 try{
  11.                         Thread.sleep(5000);
  12.                 }catch(InterruptedException e){
  13.                         e.printStackTrace();
  14.                 }
  15.                 System.out.println(name + " is running again.");
  16.         }
  17.         
  18. }
复制代码
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.         http://www.springframework.org/schema/context/spring-context-3.1.xsd">
  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配置文件的位置,如图所示:
图片2.jpg

App1.java
  1. package com.chszs;

  2. import org.springframework.context.ApplicationContext;
  3. import org.springframework.context.support.ClassPathXmlApplicationContext;
  4. import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

  5. import com.chszs.thread.PrintTask;

  6. public class App1 {

  7.         public static void main(String[] args) {
  8.                 ApplicationContext ctx =
  9.             new ClassPathXmlApplicationContext("resources/Spring-Config.xml");
  10.                 ThreadPoolTaskExecutor taskExecutor =
  11.             (ThreadPoolTaskExecutor)ctx.getBean("taskExecutor");
  12.                 taskExecutor.execute(new PrintTask("Thread 1"));
  13.                 taskExecutor.execute(new PrintTask("Thread 2"));
  14.                 taskExecutor.execute(new PrintTask("Thread 3"));
  15.                 taskExecutor.execute(new PrintTask("Thread 4"));
  16.                 taskExecutor.execute(new PrintTask("Thread 5"));
  17.                 // 检查活动的线程,如果活动线程数为0则关闭线程池
  18.                 for(;;){
  19.                         int count = taskExecutor.getActiveCount();
  20.                         System.out.println("Active Threads : " + count);
  21.                         try{
  22.                                 Thread.sleep(1000);
  23.                         }catch(InterruptedException e){
  24.                                 e.printStackTrace();
  25.                         }
  26.                         if(count==0){
  27.                                 taskExecutor.shutdown();
  28.                                 break;
  29.                         }
  30.                 }
  31.         }

  32. }
复制代码
输出:
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


















论坛徽章:
63
2010广州亚运会纪念徽章:台球
日期:2010-10-18 12:43:48茶鸡蛋
日期:2013-01-09 10:59:002013年新春福章
日期:2013-02-25 14:51:24奥运会纪念徽章:帆船
日期:2013-04-02 17:07:052013年新春福章
日期:2013-04-08 17:42:48奥运纪念徽章
日期:2013-07-18 13:55:12优秀写手
日期:2013-12-18 09:29:10马上有车
日期:2014-03-20 16:13:24马上有房
日期:2014-03-20 16:14:11马上有钱
日期:2014-03-20 16:14:11
 楼主| 发表于 2012-11-23 23:17 | 显示全部楼层
本帖最后由 chszs 于 2012-11-23 23:17 编辑

例子3:Spring线程池结合Spring托管Bean。

本例仍然使用ThreadPoolTaskExecutor类,并使用@Component注释声明Spring的托管Bean。
下面的例子PrintTask2是Spring的托管Bean,使用@Autowired注释简化代码。
PrintTask2.java
  1. package com.chszs.thread;

  2. import org.springframework.context.annotation.Scope;
  3. import org.springframework.stereotype.Component;

  4. @Component
  5. @Scope("prototype")
  6. public class PrintTask2 implements Runnable {
  7.         String name;

  8.         public void setName(String name) {
  9.                 this.name = name;
  10.         }
  11.         
  12.         @Override
  13.         public void run(){
  14.                 System.out.println(name + " is running.");
  15.                 try{
  16.                         Thread.sleep(5000);
  17.                 }catch(InterruptedException e){
  18.                         e.printStackTrace();
  19.                 }
  20.                 System.out.println(name + " is running again.");
  21.         }
  22. }
复制代码
AppConfig.java
  1. package com.chszs.config;

  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.ComponentScan;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

  6. @Configuration
  7. @ComponentScan(basePackages="com.chszs.thread")
  8. public class AppConfig {
  9.         @Bean
  10.         public ThreadPoolTaskExecutor taskExecutor(){
  11.                 ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
  12.                 pool.setCorePoolSize(5);
  13.                 pool.setMaxPoolSize(10);
  14.                 pool.setWaitForTasksToCompleteOnShutdown(true);
  15.                 return pool;
  16.         }
  17. }
复制代码
App2.java
  1. package com.chszs;

  2. import org.springframework.context.ApplicationContext;
  3. import org.springframework.context.annotation.AnnotationConfigApplicationContext;
  4. import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

  5. import com.chszs.config.AppConfig;
  6. import com.chszs.thread.PrintTask2;

  7. public class App2 {
  8.         public static void main(String[] args) {
  9.                 ApplicationContext ctx =
  10.             new AnnotationConfigApplicationContext(AppConfig.class);
  11.                 ThreadPoolTaskExecutor taskExecutor =
  12.             (ThreadPoolTaskExecutor)ctx.getBean("taskExecutor");
  13.                
  14.                 PrintTask2 printTask1 = (PrintTask2)ctx.getBean("printTask2");
  15.                 printTask1.setName("Thread 1");
  16.                 taskExecutor.execute(printTask1);
  17.                
  18.                 PrintTask2 printTask2 = (PrintTask2)ctx.getBean("printTask2");
  19.                 printTask2.setName("Thread 2");
  20.                 taskExecutor.execute(printTask2);
  21.                
  22.                 PrintTask2 printTask3 = (PrintTask2)ctx.getBean("printTask2");
  23.                 printTask3.setName("Thread 3");
  24.                 taskExecutor.execute(printTask3);
  25.                
  26.                 for(;;){
  27.                         int count = taskExecutor.getActiveCount();
  28.                         System.out.println("Active Threads : " + count);
  29.                         try{
  30.                                 Thread.sleep(1000);
  31.                         }catch(InterruptedException e){
  32.                                 e.printStackTrace();
  33.                         }
  34.                         if(count==0){
  35.                                 taskExecutor.shutdown();
  36.                                 break;
  37.                         }
  38.                 }
  39.         }

  40. }
复制代码
输出:
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框架在多线程方面的强大之处!!

使用道具 举报

回复
认证徽章
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
发表于 2012-11-24 10:34 | 显示全部楼层
很有趣的例子,推荐!

使用道具 举报

回复
论坛徽章:
0
发表于 2013-7-17 17:46 | 显示全部楼层
学习了

使用道具 举报

回复
论坛徽章:
0
发表于 2013-12-5 11:52 | 显示全部楼层
学习了   

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 
京ICP备09055130号-4  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表