• 自己写的关于生产者与消费者模式,还有定时任务的demo


    为了加深对生产者消费者模式的理解,特意写了这个demo,里面还包含了一个自己写的定时任务。代码下载地址:http://download.csdn.net/detail/li_yan_fei/9811572

    是个maven项目,只用了spring框架。


    学到的内容有3个

    第一:加深了对生产者消费者模式的理解

    第二:java Object 的wait() timeout数值如果等于0,则会造成线程一直等待下去,除非被notify唤醒

    第三:java中main函数主线程死掉不会影响其他线程的正常执行(除了守护线程)。因为main函数主线程和其他非守护线程是一样的。


    代码:

    1.一个实现了按时间排序的队列

    1. package com.lyf.task;
    2. import java.lang.reflect.InvocationTargetException;
    3. import java.util.ArrayList;
    4. import java.util.List;
    5. import org.apache.commons.beanutils.BeanUtils;
    6. import com.lyf.bean.TaskInfo;
    7. /**
    8. * @ClassName: TaskStack
    9. * @Description: 实现了一个按照时间顺序排列的队列
    10. * @author yanfei.li
    11. * @date 2017年4月10日 下午1:53:49
    12. * @Company:
    13. */
    14. public class TaskStack {
    15. private List<TaskInfo> queue = new ArrayList<TaskInfo>();
    16. public TaskStack() {
    17. }
    18. /**
    19. * 功能描述: 往队列里塞任务
    20. * @Title: push
    21. * @author yanfei.li
    22. * @date 2017年4月11日 上午11:41:50
    23. * @param taskInfo
    24. * @return void
    25. * @throws
    26. */
    27. public synchronized void push(TaskInfo taskInfo) {
    28. // 如果是空队列,直接将任务放进去就可以了
    29. if (this.queue.isEmpty()) {
    30. this.queue.add(taskInfo);
    31. // 唤醒正在调用pop的消费者线程
    32. this.notify();
    33. return;
    34. }
    35. // 如果队列不是空的,就要比较执行时间了,根据执行时间排序
    36. for (int index = 0; index < this.queue.size(); index++) {
    37. TaskInfo info = this.queue.get(index);
    38. if (info.getRunTime() > taskInfo.getRunTime()) {
    39. this.queue.add(index, info);
    40. this.notify();
    41. return;
    42. }
    43. }
    44. }
    45. /**
    46. * 功能描述: 从队列里取任务
    47. * @Title: pop
    48. * @author yanfei.li
    49. * @date 2017年4月11日 上午11:41:28
    50. * @return TaskInfo
    51. * @throws
    52. */
    53. public synchronized TaskInfo pop() {
    54. // 如果队列里没有,就释放锁,等待唤醒
    55. if (this.queue.isEmpty()) {
    56. try {
    57. this.wait();
    58. } catch (InterruptedException e) {
    59. e.printStackTrace();
    60. }
    61. }
    62. while (true) {
    63. TaskInfo taskInfo = this.queue.get(0);
    64. Long now = System.currentTimeMillis();
    65. if (now >= taskInfo.getRunTime()) {// 如果取出的任务到了执行的时间了,就返回该任务并且从队列中移除此任务。这里一定要注意了 判断条件一定要有=号,因为很可能出现相等的情况,如果进入了else中,就会造成wait(0).如果没有notify就一直等下去了
    66. this.queue.remove(0);
    67. return taskInfo;
    68. } else {
    69. try {
    70. System.out.println("pop--------" + (taskInfo.getRunTime() - now));
    71. this.wait(taskInfo.getRunTime() - now);
    72. } catch (InterruptedException e) {
    73. e.printStackTrace();
    74. }
    75. }
    76. }
    77. }
    78. /**
    79. * 功能描述: 从队列里移除任务
    80. * @Title: remove
    81. * @author yanfei.li
    82. * @date 2017年4月11日 上午11:41:06
    83. * @param taskInfo
    84. * @return void
    85. * @throws
    86. */
    87. public synchronized void remove(TaskInfo taskInfo) {
    88. this.queue.remove(taskInfo);
    89. }
    90. /**
    91. * 功能描述: 返回队列里所有的任务
    92. * @Title: getAll
    93. * @author yanfei.li
    94. * @date 2017年4月11日 上午11:40:36
    95. * @return List<TaskInfo>
    96. * @throws
    97. */
    98. public synchronized List<TaskInfo> getAll() {
    99. List<TaskInfo> retList = new ArrayList<TaskInfo>();
    100. for (TaskInfo taskInfo : this.queue) {
    101. try {
    102. TaskInfo retTask = new TaskInfo();
    103. BeanUtils.copyProperties(retTask, taskInfo);
    104. retList.add(retTask);
    105. } catch (IllegalAccessException e) {
    106. // TODO Auto-generated catch block
    107. e.printStackTrace();
    108. } catch (InvocationTargetException e) {
    109. // TODO Auto-generated catch block
    110. e.printStackTrace();
    111. }
    112. }
    113. return retList;
    114. }
    115. }

    2.消费者

    1. package com.lyf.task;
    2. import java.util.concurrent.ExecutorService;
    3. import java.util.concurrent.Executors;
    4. import com.lyf.bean.TaskInfo;
    5. import com.lyf.util.SpringContextUtils;
    6. /**
    7. * @ClassName: TaskExecutor
    8. * @Description: 任务执行器,相当于消费者
    9. * @author yanfei.li
    10. * @date 2017年4月10日 下午1:52:00
    11. * @Company:
    12. *
    13. */
    14. public class TaskExecutor implements Runnable {
    15. private TaskStack taskStack = null;//任务队列
    16. private ExecutorService fixedThreadPool = null;//线程执行池,选择的固定线程池大小,由sping初始化
    17. public TaskExecutor(TaskStack taskStack,int poolSize) {
    18. this.taskStack = taskStack;
    19. this.fixedThreadPool = Executors.newFixedThreadPool(poolSize);
    20. }
    21. public void run() {
    22. while(true){
    23. try {
    24. //获取当前要执行的任务
    25. TaskInfo taskInfo = taskStack.pop();
    26. //解析taskinfo信息,获取真正执行的task
    27. TaskInterface instance = (TaskInterface)SpringContextUtils.getBean(taskInfo.getApi());
    28. //将任务信息,传递给将要执行的task
    29. instance.setTaskInfo(taskInfo);
    30. //将任务放到线程池中执行
    31. this.fixedThreadPool.submit(instance);
    32. //如果是周期性的任务,则计算出下次执行时间,然后放到队列中
    33. if(instance.hasNext()){
    34. this.taskStack.push(instance.next());
    35. }
    36. } catch (Exception e) {
    37. e.printStackTrace();
    38. }
    39. }
    40. }
    41. }

    3.任务bean

    1. package com.lyf.bean;
    2. import java.io.Serializable;
    3. /**
    4. * @ClassName: TaskInfo
    5. * @Description: 任务实体
    6. * @author yanfei.li
    7. * @date 2017年4月10日 下午1:54:58
    8. * @Company:
    9. *
    10. */
    11. public class TaskInfo implements Serializable {
    12. private static final long serialVersionUID = 8609311967819063807L;
    13. private String id;// 任务id
    14. private String type;// 任务类型
    15. private String runAt;// 执行时间规则
    16. private String cron;// cron表达式
    17. private long runTime;// 执行时间
    18. private String api;// 执行接口
    19. private Object[] params;// 任务参数
    20. public String getId() {
    21. return id;
    22. }
    23. public void setId(String id) {
    24. this.id = id;
    25. }
    26. public String getType() {
    27. return type;
    28. }
    29. public void setType(String type) {
    30. this.type = type;
    31. }
    32. public String getRunAt() {
    33. return runAt;
    34. }
    35. public void setRunAt(String runAt) {
    36. this.runAt = runAt;
    37. }
    38. public String getCron() {
    39. return cron;
    40. }
    41. public void setCron(String cron) {
    42. this.cron = cron;
    43. }
    44. public long getRunTime() {
    45. return runTime;
    46. }
    47. public void setRunTime(long runTime) {
    48. this.runTime = runTime;
    49. }
    50. public String getApi() {
    51. return api;
    52. }
    53. public void setApi(String api) {
    54. this.api = api;
    55. }
    56. public Object[] getParams() {
    57. return params;
    58. }
    59. public void setParams(Object[] params) {
    60. this.params = params;
    61. }
    62. }

    4.任务接口

    1. package com.lyf.task;
    2. import com.lyf.bean.TaskInfo;
    3. /**
    4. * @ClassName: TaskInterface
    5. * @Description: TODO
    6. * @author yanfei.li
    7. * @date 2017年4月11日 下午12:00:10
    8. * @Company:
    9. *
    10. */
    11. public interface TaskInterface extends Runnable {
    12. /**
    13. * 功能描述: 设置任务
    14. * @Title: setTaskInfo
    15. * @author yanfei.li
    16. * @date 2017年4月11日 下午12:03:28
    17. * @param taskInfo
    18. * @return void
    19. * @throws
    20. */
    21. public void setTaskInfo(TaskInfo taskInfo);
    22. /**
    23. * 功能描述: 判断此任务是否还需要执行,针对的是循环性的任务
    24. * @Title: hasNext
    25. * @author yanfei.li
    26. * @date 2017年4月11日 下午12:02:14
    27. * @return boolean
    28. * @throws
    29. */
    30. public boolean hasNext();
    31. /**
    32. * 功能描述: 返回下次要执行的任务
    33. * @Title: next
    34. * @author yanfei.li
    35. * @date 2017年4月11日 下午12:02:18
    36. * @return TaskInfo
    37. * @throws
    38. */
    39. public TaskInfo next();
    40. }
    5.实现了任务接口的任务抽象模板类

    1. package com.lyf.task;
    2. import com.lyf.bean.TaskInfo;
    3. import com.lyf.util.SpringCronResolveUtil;
    4. /**
    5. * @ClassName: TaskInstance
    6. * @Description: 任务执行的模板类
    7. * @author yanfei.li
    8. * @date 2017年4月11日 下午2:47:57
    9. * @Company:
    10. *
    11. */
    12. public abstract class TaskInstance implements TaskInterface {
    13. protected TaskInfo taskInfo;
    14. public void run() {
    15. try {
    16. this.before();
    17. this.execute();
    18. this.after();
    19. } catch (Exception e) {
    20. // TODO Auto-generated catch block
    21. e.printStackTrace();
    22. } finally {
    23. //如果要记录日志什么的,可以放到这里
    24. }
    25. }
    26. /**
    27. * 功能描述: 任务执行前执行的方法,比如做一些初始化工作
    28. * @Title: before
    29. * @author yanfei.li
    30. * @date 2017年4月11日 下午2:50:43
    31. * @return void
    32. * @throws
    33. */
    34. protected abstract void before() throws Exception;
    35. /**
    36. * 功能描述: 任务执行的具体方法
    37. * @Title: excute
    38. * @author yanfei.li
    39. * @date 2017年4月11日 下午2:51:25
    40. * @return void
    41. * @throws
    42. */
    43. protected abstract void execute() throws Exception;
    44. /**
    45. * 功能描述: 任务执行完后执行的方法
    46. * @Title: after
    47. * @author yanfei.li
    48. * @date 2017年4月11日 下午2:51:41
    49. * @return void
    50. * @throws
    51. */
    52. protected abstract void after() throws Exception;
    53. public void setTaskInfo(TaskInfo taskInfo) {
    54. this.taskInfo = taskInfo;
    55. }
    56. public boolean hasNext() {
    57. if (this.taskInfo != null && !this.taskInfo.getRunAt().equals("now")) {
    58. return true;
    59. }
    60. return false;
    61. }
    62. public TaskInfo next() {
    63. if (this.taskInfo != null) {
    64. this.taskInfo.setRunTime(
    65. SpringCronResolveUtil.nextExecutionTime(this.taskInfo.getCron(), this.taskInfo.getRunTime()));
    66. System.out.println("next===========" + (taskInfo.getRunTime() - System.currentTimeMillis()));
    67. return this.taskInfo;
    68. }
    69. return null;
    70. }
    71. }

    6.具体任务实现类

    1. package com.lyf.task;
    2. import org.springframework.context.annotation.Scope;
    3. import org.springframework.stereotype.Service;
    4. @Service("MyTask")
    5. @Scope("prototype")
    6. public class MyTask extends TaskInstance {
    7. @Override
    8. protected void before() throws Exception {
    9. System.out.println("MyTask--------------before-------------");
    10. }
    11. @Override
    12. protected void execute() throws Exception {
    13. System.out.println("MyTask--------------execute-------------");
    14. }
    15. @Override
    16. protected void after() throws Exception {
    17. System.out.println("MyTask--------------after-------------");
    18. }
    19. }

    7.任务service

    1. package com.lyf.task;
    2. import com.lyf.bean.TaskInfo;
    3. public interface TaskService {
    4. public void startTask(TaskInfo task);
    5. }


    8.实现类


    1. package com.lyf.task;
    2. import com.lyf.bean.TaskInfo;
    3. import com.lyf.util.SpringCronResolveUtil;
    4. public class TaskServiceImpl implements TaskService{
    5. private TaskStack taskStack = null;
    6. private TaskExecutor executor = null;
    7. public TaskServiceImpl(Integer poolSize) {
    8. this.taskStack = new TaskStack();
    9. if(poolSize != null){
    10. executor = new TaskExecutor(this.taskStack, poolSize);
    11. new Thread(executor).start();
    12. }
    13. this.init();
    14. }
    15. private void init(){
    16. //做一些其他的初始化工作
    17. }
    18. public void startTask(TaskInfo task) {
    19. if (task == null) {
    20. return;
    21. }
    22. //首次执行,设置runTime
    23. if (task.getRunAt().equals("now")) {
    24. task.setRunTime(System.currentTimeMillis() - 1);
    25. } else {
    26. if (task.getCron() == null || "".equals(task.getCron().trim())) {
    27. return;
    28. }
    29. task.setRunTime(SpringCronResolveUtil.nextExecutionTime(task.getCron()));
    30. }
    31. this.taskStack.push(task);
    32. }
    33. }


    9.从spring容器中获取bean的工具类(在多线程环境下使用spring注解无法注入bean,所以需要手动获取bean



    1. package com.lyf.util;
    2. import org.springframework.beans.BeansException;
    3. import org.springframework.context.ApplicationContext;
    4. import org.springframework.context.ApplicationContextAware;
    5. public class SpringContextUtils implements ApplicationContextAware {
    6. private static ApplicationContext applicationContext = null;
    7. /**
    8. * 当继承了ApplicationContextAware类之后,那么程序在调用
    9. * getBean(String)的时候会自动调用该方法,不用自己操作
    10. */
    11. public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    12. SpringContextUtils.applicationContext = applicationContext;
    13. }
    14. public static ApplicationContext getApplicationContext(){
    15. return SpringContextUtils.applicationContext;
    16. }
    17. /**
    18. * 功能描述: 根据name从spring容器中返回bean
    19. * @Title: getBean
    20. * @author yanfei.li
    21. * @date 2017年4月11日 下午1:47:17
    22. * @param name
    23. * @throws BeansException
    24. * @return Object
    25. */
    26. public static Object getBean(String name)throws BeansException{
    27. return applicationContext.getBean(name);
    28. }
    29. /**
    30. * 功能描述: 根据name和类型从spring容器中返回bean
    31. * @Title: getBean
    32. * @author yanfei.li
    33. * @date 2017年4月11日 下午1:46:46
    34. * @param name
    35. * @param requireType
    36. * @throws BeansException
    37. * @return Object
    38. */
    39. public static <T> Object getBean(String name,Class<T> requireType)throws BeansException{
    40. return applicationContext.getBean(name,requireType);
    41. }
    42. }

    10.解析cron表达式的util(表达式只能是以空格分割的包含6个字符的字符串,不然会报错


    1. package com.lyf.util;
    2. import java.util.Date;
    3. import org.springframework.scheduling.support.CronSequenceGenerator;
    4. /**
    5. * @ClassName: SpringCronResolveUtil
    6. * @Description: 解析cron字符串的工具类
    7. * @author yanfei.li
    8. * @date 2017年4月11日 下午2:59:44
    9. * @Company:
    10. *
    11. */
    12. public class SpringCronResolveUtil {
    13. /**
    14. * 功能描述: 根据当前时间计算并返回下次执行时间
    15. * @Title: nextExecutionTime
    16. * @author yanfei.li
    17. * @date 2017年4月11日 下午3:00:56
    18. * @param cron 表达式字符串,包含6个以空格分开的字符
    19. * @return long
    20. * @throws
    21. */
    22. public static long nextExecutionTime(String cron){
    23. CronSequenceGenerator cronSequenceGenerator = new CronSequenceGenerator(cron);
    24. Date lastTime = new Date();
    25. Date nexDate = cronSequenceGenerator.next(lastTime);
    26. return nexDate.getTime();
    27. }
    28. /**
    29. * 功能描述: 根据最后一次执行时间计算并返回下次执行时间
    30. * @Title: nextExecutionTime
    31. * @author yanfei.li
    32. * @date 2017年4月11日 下午3:00:23
    33. * @param cron 表达式字符串,一定要是包含6个以空格分离的字符
    34. * @param lastTime 最近的执行时间
    35. * @return long
    36. * @throws
    37. */
    38. public static long nextExecutionTime(String cron,long lastTime) {
    39. Date date = new Date(lastTime);
    40. CronSequenceGenerator cronSequenceGenerator = new CronSequenceGenerator(cron);
    41. Date nexDate = cronSequenceGenerator.next(date);
    42. return nexDate.getTime();
    43. }
    44. public static void main(String[] args) {
    45. String cron = "0/10 * * * * ? ";
    46. System.out.println("当前时间:" + new Date().getTime());
    47. System.out.println("下一次时间:" + nextExecutionTime(cron));
    48. }
    49. }


    11.测试


    1. package com.lyf.producerandconsumer;
    2. import org.springframework.context.ApplicationContext;
    3. import org.springframework.context.support.ClassPathXmlApplicationContext;
    4. import com.lyf.bean.TaskInfo;
    5. import com.lyf.task.TaskService;
    6. import com.lyf.util.SpringContextUtils;
    7. /**
    8. * @ClassName: TestMain
    9. * @Description: 测试
    10. * @author yanfei.li
    11. * @date 2017年4月11日 下午6:20:30
    12. * @Company:
    13. *
    14. */
    15. public class TestMain {
    16. public static void main(String[] args) throws InterruptedException {
    17. System.out.println("---------------");
    18. ApplicationContext ac = new ClassPathXmlApplicationContext("com/lyf/task/local-spring.xml");
    19. TaskInfo taskInfo = new TaskInfo();
    20. taskInfo.setApi("MyTask");
    21. taskInfo.setRunAt("some");
    22. taskInfo.setCron("0/10 * * * * ?");//每隔10秒执行一次
    23. taskInfo.setType("me");
    24. System.out.println("++++++++++++++++" + ac);
    25. TaskService taskService = (TaskService) SpringContextUtils.getBean("TaskService");
    26. taskService.startTask(taskInfo);
    27. System.out.println("===========" + taskService);
    28. //主线程的死掉,不会影响其他线程的继续执行,除非是守护线程。
    29. }
    30. }


    12.pom.xml



    1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    3. <modelVersion>4.0.0</modelVersion>
    4. <groupId>com.lyf</groupId>
    5. <artifactId>producerandconsumer</artifactId>
    6. <version>0.0.1-SNAPSHOT</version>
    7. <packaging>jar</packaging>
    8. <name>producerandconsumer</name>
    9. <url>http://maven.apache.org</url>
    10. <properties>
    11. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    12. </properties>
    13. <dependencies>
    14. <dependency>
    15. <groupId>junit</groupId>
    16. <artifactId>junit</artifactId>
    17. <version>3.8.1</version>
    18. <scope>test</scope>
    19. </dependency>
    20. <!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils -->
    21. <dependency>
    22. <groupId>commons-beanutils</groupId>
    23. <artifactId>commons-beanutils</artifactId>
    24. <version>1.8.3</version>
    25. </dependency>
    26. <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
    27. <dependency>
    28. <groupId>org.springframework</groupId>
    29. <artifactId>spring-aop</artifactId>
    30. <version>4.0.4.RELEASE</version>
    31. </dependency>
    32. <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
    33. <dependency>
    34. <groupId>org.springframework</groupId>
    35. <artifactId>spring-beans</artifactId>
    36. <version>4.0.4.RELEASE</version>
    37. </dependency>
    38. <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
    39. <dependency>
    40. <groupId>org.springframework</groupId>
    41. <artifactId>spring-context</artifactId>
    42. <version>4.0.4.RELEASE</version>
    43. </dependency>
    44. <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
    45. <dependency>
    46. <groupId>org.springframework</groupId>
    47. <artifactId>spring-core</artifactId>
    48. <version>4.0.4.RELEASE</version>
    49. </dependency>
    50. <!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
    51. <dependency>
    52. <groupId>org.springframework</groupId>
    53. <artifactId>spring-tx</artifactId>
    54. <version>4.0.4.RELEASE</version>
    55. </dependency>
    56. <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
    57. <dependency>
    58. <groupId>org.springframework</groupId>
    59. <artifactId>spring-web</artifactId>
    60. <version>4.0.4.RELEASE</version>
    61. </dependency>
    62. <!-- https://mvnrepository.com/artifact/org.springframework/spring-expression -->
    63. <dependency>
    64. <groupId>org.springframework</groupId>
    65. <artifactId>spring-expression</artifactId>
    66. <version>4.0.4.RELEASE</version>
    67. </dependency>
    68. <!-- https://mvnrepository.com/artifact/aopalliance/aopalliance -->
    69. <dependency>
    70. <groupId>aopalliance</groupId>
    71. <artifactId>aopalliance</artifactId>
    72. <version>1.0</version>
    73. </dependency>
    74. <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
    75. <dependency>
    76. <groupId>org.aspectj</groupId>
    77. <artifactId>aspectjweaver</artifactId>
    78. <version>1.8.0</version>
    79. </dependency>
    80. <!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
    81. <dependency>
    82. <groupId>commons-logging</groupId>
    83. <artifactId>commons-logging</artifactId>
    84. <version>1.1.3</version>
    85. </dependency>
    86. </dependencies>
    87. </project>

    13.spring.xml


    
    
    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
    4. xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
    5. xmlns:aop="http://www.springframework.org/schema/aop"
    6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    7. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    8. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
    9. http://www.springframework.org/schema/aop
    10. http://www.springframework.org/schema/aop/spring-aop.xsd ">
    11. <!-- 启动注解扫描 -->
    12. <context:annotation-config/>
    13. <!-- 指定扫描的路径 -->
    14. <context:component-scan base-package="com.lyf.*" >
    15. <!-- 不对controller的注解 做处理,过滤掉,是为了和springmvc整合时,防止重复扫描,造成bean初始化2次-->
    16. <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    17. </context:component-scan>
    18. <bean id="springUtils" class="com.lyf.util.SpringContextUtils"/>
    19. <bean name="TaskService" class="com.lyf.task.TaskServiceImpl">
    20. <constructor-arg>
    21. <value>5</value>
    22. </constructor-arg>
    23. </bean>
    24. </beans>


    14.测试结果(每隔十秒执行一次,只贴出了部分打印数据


    1. ++++++++++++++++org.springframework.context.support.ClassPathXmlApplicationContext@23e352bf: startup date [Wed Apr 12 11:44:46 GMT+08:00 2017]; root of context hierarchy
    2. ===========com.lyf.task.TaskServiceImpl@2f54745e
    3. pop--------3621
    4. MyTask--------------before-------------
    5. MyTask--------------execute-------------
    6. MyTask--------------after-------------
    7. next===========9997
    8. pop--------9997
    9. MyTask--------------before-------------
    10. MyTask--------------execute-------------
    11. MyTask--------------after-------------
    12. next===========9999
    13. pop--------9999
    14. MyTask--------------before-------------
    15. MyTask--------------execute-------------
    16. MyTask--------------after-------------



  • 相关阅读:
    MFC 将文件拖进对话框获得文件信息
    微软历史最高市值是多少?
    ZooKeeper的学习与应用
    OutputCache祥解
    本人的微博转移
    java list三种遍历方法性能比較
    VS2010旗舰版安装图解
    SSL协议具体解释
    freemarker字符串拼接
    [java web 入门](一)MyEclipse &amp; HelloWorld 记录
  • 原文地址:https://www.cnblogs.com/jpfss/p/9447427.html
Copyright © 2020-2023  润新知