使用線程池模擬處理耗時任務,通過websocket提高用戶體驗


前言

在文章開始之前,詢問一下大家平時工作中后端處理批量任務(耗時任務)的時候,前端是如何告知用戶任務的執行情況的?

樓主對這個問題想了下,決定使用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/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM