为了加深对生产者消费者模式的理解,特意写了这个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-------------

自己写的关于生产者与消费者模式,还有定时任务的demo的更多相关文章

  1. 使用libuv实现生产者和消费者模式

    生产者和消费者模式(Consumer + Producer model) 用于把耗时操作(生产线程),分配给一个或者多个额外线程执行(消费线程),从而提高生产线程的响应速度(并发能力) 定义 type ...

  2. java生产者与消费者模式

    前言: 生产者和消费者模式是我们在学习多线程中很经典的一个模式,它主要分为生产者和消费者,分别是两个线程, 目录 一:生产者和消费者模式简介 二:生产者和消费者模式的实现 声明:本例来源于java经典 ...

  3. condition版生产者与消费者模式

    1.简介 在爬虫中,生产者与消费者模式是经常用到的.我能想到的比较好的办法是使用redis或者mongodb数据库构造生产者消费者模型.如果直接起线程进行构造生产者消费者模型,线程容易假死,也难以构造 ...

  4. Java并发编程(4)--生产者与消费者模式介绍

    一.前言 这种模式在生活是最常见的,那么它的场景是什么样的呢? 下面是我假象的,假设有一个仓库,仓库有一个生产者和一个消费者,消费者过来消费的时候会检测仓库中是否有库存,如果没有了则等待生产,如果有就 ...

  5. Java多线程设计模式(2)生产者与消费者模式

    1 Producer-Consumer Pattern Producer-Consumer Pattern主要就是在生产者与消费者之间建立一个“桥梁参与者”,用来解决生产者线程与消费者线程之间速度的不 ...

  6. 【爬虫】Condition版的生产者和消费者模式

    Condition版的生产者和消费者模式 threading.Condition 在没有数据的时候处于阻塞状态,有数据可以使用notify的函数通知等等待状态的线程运作 threading.Condi ...

  7. 【爬虫】Load版的生产者和消费者模式

    ''' Lock版的生产者和消费者模式 ''' import threading import random import time gMoney = 1000 # 原始金额 gLoad = thre ...

  8. java 线程并发(生产者、消费者模式)

    线程并发协作(生产者/消费者模式) 多线程环境下,我们经常需要多个线程的并发和协作.这个时候,就需要了解一个重要的多线程并发协作模型“生产者/消费者模式”. Ø 什么是生产者? 生产者指的是负责生产数 ...

  9. java进阶(40)--wait与notify(生产者与消费者模式)

    文档目录: 一.概念 二.wait的作用 三.notify的作用 四.生产者消费者模式 五.举例 ---------------------------------------分割线:正文------ ...

随机推荐

  1. BZOJ3511: 土地划分(最小割)

    Description Y国有N座城市,并且有M条双向公路将这些城市连接起来,并且任意两个城市至少有一条路径可以互达. Y国的国王去世之后,他的两个儿子A和B都想成为新的国王,但他们都想让这个国家更加 ...

  2. LuoguP4016 负载平衡问题(费用流)

    题目描述 G 公司有 n 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等.如何用最少搬运量可以使 n 个仓库的库存数量相同.搬运货物时,只能在相邻的仓库之间搬运. 输入输出格式 输入格式: ...

  3. readonly&&declare&&unset &&export&&env环境变量

    readonly命令用于定义只读shell变量和shell函数.readonly命令的选项-p可以输出显示系统中所有定义的只读变量. 选项 -f:定义只读函数: -a:定义只读数组变量: -p:显示系 ...

  4. 【习题 8-10 UVA - 1614】Hell on the Markets

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 证明:前i个数一定能凑够1..sum[i]中的所有数字 i=1时显然成立. 现在假设i>=2时结论成立 即前i个数字能凑出1. ...

  5. ThinkPad E431 获取无限网络的驱动

    sudo apt-get install linux-headers-generic build-essential dkms    sudo apt-get install linux-source ...

  6. VMware虚拟机XP系统安装

    转载:http://jingyan.baidu.com/article/54b6b9c00e2f452d593b4762.html

  7. LinearLayout -设置负值属性

    1.我们调整两个控件的位置的时候,数值不仅仅是正数,负的也行,这时候只不过是跑到相对位置的另一边去了,例如 <ImageView android:id="@+id/image" ...

  8. 轻松学习Linux之Shell的常用过滤器

    下载高清视频: http://down.51cto.com/data/157818    大小3:MB      时长: 7分钟 更多内容见: Linux爱好者的圣诞大餐-轻松学习Linux系列多媒体 ...

  9. Java学习笔记七 常用API对象三

    一.泛型:简单说就是对对象类型进行限定的技术 public class GenericDemo { public static void main(String[] args){ /*泛型作为1.5版 ...

  10. 数组-reduce方法

    转自: https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/139 实现 convert 方法,把原始 list ...