场景简单,其实就是在做WEB请求的时候,处理的结果需要同时通知到一个第三方服务器,通知后再把结果返回给客户端。

现在这个通知只是一个简单通知,如果直接加在客户端请求里面,客户端会在请求第三方服务器时堵塞。另外为了客户端不能超时,所以通知失败后也不敢多次请求。

这里可以使用定制任务来解决这个问题,一个客户端请求后产生一个定制的任务,然后服务后台进行多线程的异步处理,这样就会大大减少客户端的请求时间,同样最大程度保证这个通知是及时成功给第三方的。

定制任务我们需要一张表,来存储任务。同时需要多线程来执行这些任务。至于谁来开启这些任务,你可以使用定时器:http://javacui.com/framework/24.html,也可以使用后台线程。因为定时器已经有示例了,这里来说下后台线程。

因为是WEB服务,在服务启动的时候注册一个启动监听:

webListener

cn.com.vogue.listener.InitListener

然后我们来实现这个监听处理,主要任务就是开启一个后台线程,实时查询是否有需要执行的任务,有的话就分发任务给子线程。

同时为了系统的可配性,这个主线程是否开启做一个配置项,加载的时候判断一下即可:isRunRulThread=0import javax.servlet.ServletContextEvent;

import javax.servlet.ServletContextListener;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import cn.com.vogue.task.UrlTask;

import cn.com.vogue.utils.ResourceUrl;

import cn.com.vogue.utils.SpringFactory;

/**

* 初始化

*/

public class InitListener implements ServletContextListener {

private static Logger logger = LoggerFactory.getLogger(InitListener.class);

public void contextDestroyed(ServletContextEvent sce) {

}

public void contextInitialized(ServletContextEvent sce) {

if(ResourceUrl.isRunRulThread == 1){

logger.warn("==========================>>>>>>>URL请求定制任务开启");

UrlTask urlTaskBase = new UrlTask(); // 开始任务

SpringFactory.executorService.execute(urlTaskBase);

}

}

}

这里我在SpringFactory里面定义了一个线程池,关于线程池:http://javacui.com/Theory/151.html。

为了不对对方服务器造成压力,任务子线程最多开10个,加上主线程,一共11个,所以线程池不用太大。public static ExecutorService executorService= Executors.newFixedThreadPool(11);

// 定长线程池

主线程任务:查询是否有需要执行的任务,任务分发。

子线程:处理任务。import java.util.List;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import cn.com.vogue.entity.UrlTaskBase;

import cn.com.vogue.service.systemManagement.UrlTaskBaseService;

import cn.com.vogue.utils.HttpUtils;

import cn.com.vogue.utils.SpringFactory;

public class UrlTask implements Runnable{

private static Logger logger = LoggerFactory.getLogger(UrlTask.class);

public static Integer isRun = new Integer(0);

// 该标量用于标记子线程在运行时,总线程不再派发新任务

public void run() {

while(true){

try {

UrlTaskBaseService taskSer = (UrlTaskBaseService)SpringFactory.getObject("urlTaskBaseService");

List taskList = taskSer.findUrlTaskBaseUnSucc();

if(null != taskList && taskList.size() > 0){

logger.warn("本次需要执行的任务个数:" + taskList.size() + " 个");

for(UrlTaskBase task : taskList){

Init1ListenerRun run = new Init1ListenerRun(task, taskSer);

SpringFactory.executorService.execute(run);

try {Thread.sleep(1000);} catch (Exception e) {}

}

}else{

logger.warn("没有找到要执行的任务,休眠后继续执行");

}

} catch (Exception e) {

logger.error("查询执行任务时异常", e);

}

while(isRun > 0){

try {Thread.sleep(1 * 1000);} catch (Exception e) {}

}

logger.error("60秒后进行下一次任务轮询");

try {Thread.sleep(60 * 1000);} catch (Exception e) {} // 任务休眠60秒

}

}

}

class Init1ListenerRun implements Runnable {

private static Logger logger = LoggerFactory.getLogger(Init1ListenerRun.class);

public void run() {

synchronized (UrlTask.isRun) { UrlTask.isRun ++; }

try {

logger.warn(task.getId() + " 任务路径:" + task.getTaskUrl());

if(task.getTaskType() == 0){

String result = HttpUtils.HttpGet(task.getTaskUrl());

logger.warn(task.getId() + " 返回结果:" + result);

if(null != result && !"".equals(result)){

task.setBackStr(result);

}

task.setTryCount(task.getTryCount() + 1);

taskSer.save(task);

}else{

String result = HttpUtils.HttpPost(task.getTaskUrl(), task.getTaskBody());

logger.warn(task.getId() + " 返回结果:" + result);

if(null != result && !"".equals(result)){

task.setBackStr(result);

}

task.setTryCount(task.getTryCount() + 1);

taskSer.save(task);

}

} catch (Exception e) {

logger.error("执行任务异常", e);

}

synchronized (UrlTask.isRun) { UrlTask.isRun --; }

}

private UrlTaskBase task;

private UrlTaskBaseService taskSer;

public Init1ListenerRun(UrlTaskBase task, UrlTaskBaseService taskSer){

this.task = task;

this.taskSer = taskSer;

}

}

这里用一个标量来标记有子线程在执行,主线程则休眠。

用对象来传递需要执行的任务,实体代码如下:public class UrlTaskBase extends IdEntity{

// 请求的地址,如果是Get,则带参数

private String taskUrl;

// 请求类型 0 GET 1 POST

private int taskType;

// POST 请求参数

private String taskBody;

// 成功的标记

private String okMark;

// 实际返回结果,和 okMark 一致为成功

private String backStr;

// 尝试次数

private int tryCount;

// 创建时间

private String createTime;

}

任务分为GET请求和POST请求两种。

可以看到获取Spring对象用到了SpringFactory,关于这个对象http://javacui.com/framework/36.html。

推荐您有关于“ java定时器多线程线程池通知 ”的文章

java 多线程处理任务_用Java多线程,将任务分步骤处理相关推荐

  1. java核心教程_核心Java教程

    java核心教程 Welcome to Core Java Tutorial. I have written a lot on Core Java and Java EE frameworks. Th ...

  2. java 分割一个_分割java

    [java]分割字符串工具类,霸气 jdk自带的 java 分割字符串,分割string,可以根据多个条件去分割.比如逗号,分号,逗号或者分号. 比如一个字符串:"abc,def;gh,ij ...

  3. java武功秘籍_请问java全套内容都有什么呢?

    我整理的Java全套内容学习路线,分为6个阶段(大阶段)第一阶段:java内功心法篇 第二阶段:Java武功秘籍(经典框架) 第三阶段:Java高级功法(主流框架) 第四阶段:Java成神之路 第五阶 ...

  4. java初始化数据报_初始化java原因

    虚拟机的类加载机制 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类 即虚拟机的类加载机制. 在Java中,类型的加载.链接 ...

  5. java robot 对象_用Java Robot对象实现服务器屏幕远程监视

    用Java Robot对象实现服务器屏幕远程监视 作者:李鲁群 摘要: 有时候,在Java应用程序开发中,如:远程监控或远程教学,常常需要对计算机的屏幕进行截取,由于屏幕截取是比较接近操作系统的操作, ...

  6. java初学课程_作为java新手应该学习什么课程

    照目前IT行业发展趋势,学java的人越来越多,因为java的应用范围广,薪资待遇在IT行业里也是名列前茅,那么,作为java新手应该学习什么课程呢?动力节点java学院的小编来告诉大家新手应该学哪些 ...

  7. java正则表达式 匹配()_学习Java正则表达式(匹配、替换、查找)

    import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; public c ...

  8. 纯java分布式内存数据库_最新Java岗面试清单:分布式+Dubbo+线程+Redis+数据库+JVM+并发...

    最近可能有点闲的慌,没事就去找面试面经,整理了一波面试题.我大概是分成了Java基础.中级.高级,分布式,Spring架构,多线程,网络,MySQL,Redis缓存,JVM相关,调优,设计模式,算法与 ...

  9. java面向对象课件_《JAVA面向对象基础》PPT课件.ppt

    <<JAVA面向对象基础>PPT课件.ppt>由会员分享,可在线阅读,更多相关<<JAVA面向对象基础>PPT课件.ppt(68页珍藏版)>请在人人文库 ...

最新文章

  1. 百度健康打通医药电商服务
  2. JavaScript window.getComputedStyle()
  3. EasyDarwin开源流媒体服务器进行RTSP转发过程中将sdp由文件存储改成内存索引
  4. python常用类型的内置函数列表
  5. Golang 学习资料
  6. 微信web开发者工具初次安装无法打开的几种解决办法
  7. 安装.Net Standard 2.0, Impressive
  8. 3198元起!魅族16s开启预约:4月28日全渠道首发
  9. MapReduce案例(数据中获取最大值TopN)
  10. 对Vue生命周期的一些简单见解
  11. 程序有时能运行有时不能_学法能有什么好处?有时候觉得挺“秃”然的..
  12. linux中 qt安装教程视频,Linux 下QT安装教程
  13. 网络工程管理 第四章 路由器 RIP OSPF 及配置实验
  14. UWP 制作汉堡菜单及添加滑动手势
  15. LED Designing
  16. 移动物联网怎么激活?开户流程是怎么样的
  17. SE14 激活并调整数据库
  18. malloc、calloc、realloc、free、malloc_trim
  19. 下载并安装Windows 7 系统的步骤
  20. pycharm用不了anaconda的库

热门文章

  1. remote: error: GH007: Your push would publish a private email address.
  2. 剑指offer:面试题10- II. 青蛙跳台阶问题
  3. Udacity机器人软件工程师课程笔记(二)-样本搜索和找回-基于漫游者号模拟器
  4. 【进阶版九宫格背景图片】如何仅仅依靠background的几个属性组合搭配出酷炫的背景图片效果,并自适应任何宽高效果?
  5. a-awk外部变量传入,内部变量传出,同时过滤空格及其他字符
  6. [bzoj2259][Oibh]新型计算机_Dijkstra
  7. Hadoop概念学习系列之为什么hadoop/spark执行作业时,输出路径必须要不存在?(三十九)...
  8. Apache+PHP in MAC
  9. Apache启动时报Could not reliably determine the server's fully qualified domain name
  10. 【Math】P=NP问题