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

    1.字符串转换为时间戳可以这样做: date -d "2010-10-18 00:00:00" +%s 输出形如: 1287331200 其中,-d参数表示显示指定的字符串所表示的 ...

  2. ajax的内容

    ajax是什么? 通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新,可以局部刷新而不必整个页面整体刷新. url的简单认识: 进入服务器的三种方式: 1.localhost:端口号 ...

  3. Django项目之Web端电商网站的实战开发(三)

    说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 接着上一篇博客继续往下写 :https://blog.csdn.net/qq_41782425/article/details/8 ...

  4. 【Henu ACM Round #12 C】 Alice, Bob, Two Teams

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 考虑任意两个字符串(a,b) 假设a在b的前面 那么如果a+b>=b+a 这里的+表示字符串的链接 那么显然需要交换a,b的位 ...

  5. STL_算法_查找算法(search、find_end)

    C++ Primer 学习中. .. 简单记录下我的学习过程 (代码为主) search          //从左往右找第一个符合条件的子区间    全部容器适用 find_end  //从右往左找 ...

  6. Android自定义视图

    Android框架为我们提供了大量的视图类来帮助我们做好展示信息以及同用户进行交互的工作.然后有时候,我们的app或许需要一些在Android内建视图之外特殊的视图,那么此时我们就需要自定义视图.下面 ...

  7. HBase高速导入数据--BulkLoad

    Apache HBase是一个分布式的.面向列的开源数据库.它能够让我们随机的.实时的訪问大数据.可是如何有效的将数据导入到HBase呢?HBase有多种导入数据的方法.最直接的方法就是在MapRed ...

  8. 编程算法 - 水洼的数量 代码(C)

    水洼的数量 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 有一个大小为N*M的园子, 雨后起了积水. 八连通的积水被觉得是连接在一起的. 请求 ...

  9. 内网使用 IPV6 之Teredo篇

    这篇转载自 http://bbs.pcbeta.com/viewthread-1580771-1-1.html 上IPv6站点之Teredo篇http://bbs.pcbeta.com/viewthr ...

  10. Multiple CPUs,Multiple Cores、Hyper-Threading

    CPU Basics: Multiple CPUs, Cores, and Hyper-Threading Explained 现在多数的家用电脑,仍然使用的是 Single CPU,Multiple ...