前言

在文章开始之前,询问一下大家平时工作中后端处理批量任务(耗时任务)的时候,前端是如何告知用户任务的执行情况的?

楼主对这个问题想了下,决定使用websokect将这一过程展现给用户。

于是就有了这篇文章,跟大家一起学习。

WebSocket简单介绍

WebSocket是HTML5开始提供的一种浏览器与服务器间进行全双工通讯的网络技术。 WebSocket通信协议于2011年被IETF定为标准 RFC 6455,WebSocketAPI被W3C定为标准。

在WebSocket API中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

  ----------以上文字摘自于Wiki对WebSocket的介绍。

简单来说,WebSocket就是浏览器与服务器之间进行通讯的一种技术。

关于WebSocket出现的背景及原理,大家可看wiki中的介绍。

实例讲解

本文讲解的实例使用java语言编写,web服务器使用jetty8。

先看下对应的Servlet和WebSocket代码:

Servlet:

@WebServlet(name = "main", urlPatterns = "/main.do")
public class MainServlet extends WebSocketServlet { public WebSocket doWebSocketConnect(HttpServletRequest httpServletRequest, String s) {
return new TaskWebSocket();
} }

WebSocket使用Task对象模拟耗时任务,用线程池进行处理:

public class TaskWebSocket implements WebSocket.OnTextMessage {

    private Connection conn;

    private ExecutorService executorService;
private CompletionService completionService; private Random random = new Random(); public TaskWebSocket() {
executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
completionService = new ExecutorCompletionService<String>(executorService);
} public void onMessage(String s) {
try {
conn.sendMessage("开始执行任务");
int taskNum = 4;
for(int i = 0; i < taskNum; i ++) {
Task task = new Task(random.nextInt(20), conn, String.valueOf(i + 1));
completionService.submit(task);
}
for(int i = 0; i < taskNum; i ++) {
String result = completionService.take().get();
conn.sendMessage(result);
}
conn.sendMessage("任务执行完毕");
conn.close();
} catch (Exception e) {
e.printStackTrace();
System.err.println("error");
}
} public void onOpen(Connection connection) {
System.out.println("on Open");
this.conn = connection;
} public void onClose(int i, String s) {
System.out.println("on Close");
} } class Task implements Callable<String> { private int sleepSec;
private WebSocket.Connection conn;
private String name; public Task(int sleepSec, WebSocket.Connection conn, String name) {
this.sleepSec = sleepSec;
this.conn = conn;
this.name = name;
} public String call() throws Exception {
conn.sendMessage("任务(" + name + ")开始执行, 该任务大概会执行" + sleepSec + "秒");
Thread.sleep(sleepSec * 1000);
return "任务" + name + "执行完成";
} }

效果图:

前端js的代码就不贴了,用的是原生的websocket。

代码下载地址: https://github.com/fangjian0423/jetty8-websocket-demo

参考资料

http://zh.wikipedia.org/wiki/WebSocket

http://redstarofsleep.iteye.com/blog/1307608

http://www.ibm.com/developerworks/cn/web/1112_huangxa_websocket/

使用线程池模拟处理耗时任务,通过websocket提高用户体验的更多相关文章

  1. java线程池模拟并发

    public class CountDownLatchTest1 implements Runnable{ final AtomicInteger number = new AtomicInteger ...

  2. 客户端模拟线程线程池发送100个文件给socket

    1.线程池模拟发送100个线程发送 2.每个线程启动一个socket发送文件 3.线程池最大并发几个

  3. twisted的defer模式和线程池

    前言: 最近帮朋友review其模块服务代码, 使用的是python的twisted网络框架. 鉴于之前并没有使用过, 于是决定好好研究一番. twisted的reactor模型很好的处理了网络IO事 ...

  4. 第11章 Windows线程池(1)_传统的Windows线程池

    第11章 Windows线程池 11.1 传统的Windows线程池及API (1)线程池中的几种底层线程 ①可变数量的长任务线程:WT_EXECUTELONGFUNCTION ②Timer线程:调用 ...

  5. springboot 线程池

    我们常用ThreadPoolExecutor提供的线程池服务,springboot框架提供了@Async注解,帮助我们更方便的将业务逻辑提交到线程池中异步执行,今天我们就来实战体验这个线程池服务: 本 ...

  6. springboot线程池的使用和扩展(转)

    springboot线程池的使用和扩展 我们常用ThreadPoolExecutor提供的线程池服务,springboot框架提供了@Async注解,帮助我们更方便的将业务逻辑提交到线程池中异步执行, ...

  7. springboot线程池的使用和扩展

    我们常用ThreadPoolExecutor提供的线程池服务,springboot框架提供了@Async注解,帮助我们更方便的将业务逻辑提交到线程池中异步执行,今天我们就来实战体验这个线程池服务: 本 ...

  8. Android 线程池的类型、区别以及为何要用线程池

    每个 Android 应用进程在创建时,会同时创建一个线程,我们称之为主线程,负责更新 UI 界面以及和处理用户之间的交互,因此,在 Android 中,我们又称之为 UI 线程.一个进程中 UI 线 ...

  9. springboot线程池@Async的使用和扩展

    我们常用ThreadPoolExecutor提供的线程池服务,springboot框架提供了@Async注解,帮助我们更方便的将业务逻辑提交到线程池中异步执行,今天我们就来实战体验这个线程池服务: 本 ...

随机推荐

  1. Effective Java 56 Adhere to generally accepted naming conventions

    Typographical naming conventions Identifier Type Type Examples Package com.google.inject, org.joda.t ...

  2. 安装和配置JDK,并给出安装、配置JDK的步骤。

    1.从orcal网站下载安装包. 2.安装目录不要有汉字或空格 3.配置环境变量,增加·JAVA_HOME=jdk的全路径,修改path+%JAVA_HOME%\bin;%JAVA_HOME%\jre ...

  3. apache 开启zgip 压缩模式

    一.Apache开启gzip压缩模式在目录apache\conf\httpd.conf 配置 httpd.conf 文件: #去掉LoadModule deflate_module modules/m ...

  4. 读书笔记——Windows环境下32位汇编语言程序设计(3)一些基础知识

    声明函数用proto 定义函数用proc 局部变量只能定义,不能赋初值,类型不能用缩写. 全局变量可以定义的时候赋初值,默认值为0. 在invoke中,参数可以使用addr取址. sizeof 字节长 ...

  5. index merge的一次优化

    手机微博4040端口SQL优化 现象 某端口常态化延迟,通过使用pt-query-digest发现主要由于一条count(*)语句引发,具体如下: # .5s .58M rss, .84M vsz # ...

  6. dubbo学习之服务提供者

    1.简介 这里主要记录如何搭建一个spring框架,提供一个dubbo服务,包括详细的步骤. 2.详细步骤 2.1 项目目录结构 2.2 创建maven项目 new --> Web Projec ...

  7. 有用的MySQL语句

    摘自onefish资料库 1. 计算年数你想通过生日来计算这个人有几岁了. SELECT DATE_FORMAT(FROM_DAYS(TO_DAYS(now()) - TO_DAYS(@dateofb ...

  8. sudo: unable to resolve host xxx解决办法

    问题: root@wiki:~# sudo lsb_release -a sudo: unable to resolve host wiki No LSB modules are available. ...

  9. 二叉查找树的懒惰删除(lazy deletion)

    第四章习题:二叉查找树类实现懒惰删除,注意findMin()和findMax()(递归) 算是发布的第一篇学习笔记.也不敢保证写的代码一定正确,错了的地方请大家指正,谢谢. 直接开始吧.先谈谈数据结构 ...

  10. 记忆化搜索 codevs 2241 排序二叉树

    codevs 2241 排序二叉树 ★   输入文件:bstree.in   输出文件:bstree.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 一个边长为n的正三 ...