高級ZK:異步UI更新和后臺處理–第2部分

介紹

在第1部分中,我展示了如何在ZK應用程序中使用服務器推送和線程來執行后臺任務。 但是,這個簡單的示例具有一個重大缺陷,這使其對于實際應用程序而言是一種不好的方法:它為每個后臺任務啟動了一個新線程。

JDK5引入了ExecutorService類,該類抽象了線程詳細信息,并為我們提供了一個不錯的接口,可用于提交任務以進行后臺處理。

在這篇博客文章中,我將描述創建ZK應用程序的最重要部分,該應用程序包含一個采用字符串并以大寫形式返回的后臺任務。 完整的示例項目可在Github上找到:

https://github.com/Gekkio/blog/tree/master/2012/10/async-zk-part-2

1.創建一個ExecutorService實例

首先,我們需要一個可以在ZK代碼中使用的ExecutorService。 在大多數情況下,我們需要一個共享的單例實例,該實例可以通過依賴項注入(例如Spring)進行配置和管理。 確保只創建一次ExecutorService,并且使用應用程序將其正確關閉是非常重要的。

在這個示例項目中,我將使用一個簡單的holder類,該類管理單個靜態可用的ExecutorService實例的生命周期。 該持有人必須在zk.xml中配置為偵聽器

package sample;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;import org.zkoss.zk.ui.WebApp;
import org.zkoss.zk.ui.util.WebAppCleanup;
import org.zkoss.zk.ui.util.WebAppInit;public class SampleExecutorHolder implements WebAppInit, WebAppCleanup {private static volatile ExecutorService executor;public static ExecutorService getExecutor() {return executor;}@Overridepublic void cleanup(WebApp wapp) throws Exception {if (executor != null) {executor.shutdown();System.out.println('ExecutorService shut down');}}@Overridepublic void init(WebApp wapp) throws Exception {executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());System.out.println('Initialized an ExecutorService');}}

請注意,線程池是根據系統中的處理器使用固定大小配置的。 正確的線程池大小調整非常重要,并且取決于您打算執行的任務類型。 最大線程數也是同時進行的并發任務的最大數量!

2.編寫對后臺任務的結果進行建模的事件類

我們將使用ZK服務器推送將任務結果傳達回UI,因此必須將結果建模為ZK事件。 創建自定義Event的子類而不是將結果添加到data參數中始終是一個好主意,因為自定義類更加類型安全并且可以支持多個字段。

第一個事件類表示任務仍在運行時發送的狀態更新。 在此示例中,它將包含輸入字符串中的字符數。

package sample;import org.zkoss.zk.ui.event.Event;public class FirstStepEvent extends Event {public final int amountOfCharacters;public FirstStepEvent(int amountOfCharacters) {super('onFirstStepCompleted', null);this.amountOfCharacters = amountOfCharacters;}}

第二個事件類表示完全完成的任務。 在此示例中,它包含大寫的輸入字符串。

package sample;import org.zkoss.zk.ui.event.Event;public class SecondStepEvent extends Event {public final String upperCaseResult;public SecondStepEvent(String upperCaseResult) {super('onSecondStepCompleted', null);this.upperCaseResult = upperCaseResult;}}


3.編寫任務類

任務類應具有以下特征:

  • 它實現了Runnable
  • 它將所有必需的輸入數據作為構造函數參數(如果可能,數據應該是不可變的!)。 此輸入數據必須是線程安全的,并且通常不應包含任何與ZK相關的內容(無組件,會話等)。 例如,如果要使用文本框值作為輸入,請事先讀取該值,并且不要將文本框本身作為參數傳遞
  • 它需要一個Desktop,以及至少一個EventListener作為構造函數參數。 它們是將結果發送回UI所必需的

在此示例中,唯一的輸入數據是將用于計算任務結果的字符串。

package sample;import java.util.Locale;import org.zkoss.zk.ui.Desktop;
import org.zkoss.zk.ui.DesktopUnavailableException;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;public class SampleTask implements Runnable {private final String input;private final Desktop desktop;private final EventListener<Event> eventListener;@SuppressWarnings({ 'rawtypes', 'unchecked' })public SampleTask(String input, Desktop desktop, EventListener eventListener) {this.input = input;this.desktop = desktop;this.eventListener = eventListener;}@Overridepublic void run() {try {// Step 1Thread.sleep(10000);Executions.schedule(desktop, eventListener, new FirstStepEvent(input.length()));// Step 2Thread.sleep(10000);Executions.schedule(desktop, eventListener, new SecondStepEvent(input.toUpperCase(Locale.ENGLISH)));} catch (DesktopUnavailableException e) {System.err.println('Desktop is no longer available: ' + desktop);} catch (InterruptedException e) {}}}

注意所有構造函數參數如何存儲在私有的final字段中,以及輸入數據如何不可變(Java中字符串是不可變的!)。 該任務通過使用Thread.sleep模擬長時間運行的處理,并在“處理”完成一半時提交狀態事件。

4.在ZK作曲家中安排任務

在作曲家中使用任務非常簡單。 您只需要啟用服務器推送,并將新的任務實例提交給執行者。 一旦有可用的后臺線程可用,它將自動啟動任務。

desktop.enableServerPush(true);
// Get the executor from somewhere
executor = SampleExecutorHolder.getExecutor();
executor.execute(new SampleTask(input.getValue(), desktop, this));

在此示例中,編輯器擴展了GenericForwardComposer,該實現實現了EventListener,因此它本身可以處理產生的任務事件。 這兩個事件均由使用狀態信息更新UI的方法處理。

public void onFirstStepCompleted(FirstStepEvent event) {status.setValue('Task running: ' + event.amountOfCharacters + ' characters in input');
}public void onSecondStepCompleted(SecondStepEvent event) {status.setValue('Task finished: ' + event.upperCaseResult);
}


最后的話

使用此技術為ZK應用程序中的長期運行的任務添加強大的支持非常容易。 ZK編寫器中的結果代碼非常簡單,因為結果是使用典型的Event / EventListener范例傳遞的,該范例在ZK應用程序中非常常見。

這種技術的最大危險是線程安全錯誤,這些錯誤很難調試。 完全了解執行每段代碼的線程,并確保所有共享狀態都是完全線程安全的,這至關重要。 只要后臺任務本身不訪問其他非線程安全資源,使用不可變的輸入數據和不可變的輸出事件通常足以確保安全。 一些常見的錯誤是:

  • 在后臺任務中調用線程本地相關的庫方法(例如,任何看起來神奇地獲得某種“當前”值的方法)。 后臺線程不會自動包含與servlet線程相同的線程本地值,因此默認情況下,所有這些方法都將失敗。 例如ZK中的Sessions.getCurrent(),Executions.getCurrent()和許多Spring Security靜態方法。
  • 將非線程安全參數傳遞給后臺任務。 例如,傳遞一個可變的List,該可變的List可能在任務運行時由編寫者修改(總是制作可變集合的副本!)。
  • 在事件中傳遞非線程安全的結果數據。 例如,在結果事件中傳遞列表,而稍后將在任務中修改列表(始終復制可變集合!)。
  • 在桌面中訪問非線程安全的方法。 即使您可以在后臺任務中訪問桌面,大多數桌面方法也不是線程安全的。 例如,不能保證調用desktop.isAlive()能夠正確返回狀態(至少在ZK 6.5中,該方法依賴于非易失性字段,因此不能保證在后臺線程中可見寫入)


參考: Advanced ZK:異步UI更新和后臺處理– Jawsy Solutions技術博客博客上的JCG合作伙伴 Joonas Javanainen的第二部分 。

翻譯自: https://www.javacodegeeks.com/2012/10/advanced-zk-asynchronous-ui-updates-and-background-processing-part-2.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/370668.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/370668.shtml
英文地址,請注明出處:http://en.pswp.cn/news/370668.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

css清除浮動的原理

最近學習css發現了高度塌陷時候要清除浮動,為了理解清楚浮動原理,網上找了不少資料,發現都寫的不是很清楚,而且都是一模一樣的內容,我在里分享一下我對清楚浮動原理的理解, 如果你已經很了解什么是浮動和浮動的效果你可以直接跳轉到三.如何清除浮動(重點)閱讀 一.什么是浮動首…

SpringBoot03 項目熱部署

1 問題 在編寫springBoot項目時&#xff0c;經常需要修改代碼&#xff1b;但是每次修改代碼后都需重新啟動&#xff0c;修改的代碼才會生效 2 這么實現IDEA能夠像Eclipse那樣保存過后就可以自動進行刷新呢 將springBoot項目進行熱部署即可 3 如何實現SpringBoot項目的熱部署01 …

STM32實現流水燈

led.c #include"led.h"void Led_Init(void) {GPIO_InitTypeDef GPIO_VALUE; //???RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//???GPIO_VALUE.GPIO_ModeGPIO_Mode_Out_PP;//???? ????GPIO_VALUE.GPIO_PinGPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_…

jacob 報錯 Can't co-create object

問題&#xff1a;開始時一切正常&#xff0c;后來什么都沒該&#xff0c;出現Cant co-create object報錯&#xff0c;即是創建不了ActiveXComponent wdnew ActiveXComponent("Word.Application"); 偶爾發現任務管理器中word進程居然達到10個&#xff0c;而我沒有打開…

map分組后取前10個_map根據屬性排序、取出map前n個

/*** map根據value排序* flag 1 正序* flag 0 倒序** param map* param flag* return*/public static > LinkedHashMap sortByValue(Map map, int flag) {LinkedHashMap sortMap new LinkedHashMap<>();if (flag 1) {map.entrySet().stream().sorted(Comparator.c…

wxpython可視化_使用wxPython的繪圖模塊wxPyPlot進行數據可視化

[Python進階(四十)-數據可視化の使用matplotlib進行繪圖前言??matplotlib是基于Python語言的開源項目&#xff0c;旨在為Python提供一個數據繪圖包。我將在這篇文章中介紹matplotlib A #-*- coding: utf-8 -*- ############################################################…

在Java EE 6中將Bean驗證與JAX-RS集成

JavaBeans驗證&#xff08;Bean驗證&#xff09;是一種新的驗證模型&#xff0c;可作為Java EE 6平臺的一部分使用。 約束條件支持Bean驗證模型&#xff0c;該約束以注釋的形式出現在JavaBeans組件&#xff08;例如托管Bean&#xff09;的字段&#xff0c;方法或類上。 javax.…

如何讓浮動的元素換行??css

當你想要做成這種布局效果的時候 紫色框里面的內容那樣 它是一個列表 li元素是塊級元素 默認大小是父元素ul的寬 并且換行 如果li沒有背景的話那就不用管了 可是問題來了它不但有背景 而且是根據文字自適應的寬高 這就是inline-block類型的功能了 那么想讓li是inline-bl…

Python學習之類和實例

面向對象最重要的概念就是類&#xff08;Class&#xff09;和實例&#xff08;Instance&#xff09;&#xff0c;必須牢記類是抽象的模板&#xff0c;比如Student類&#xff0c;而實例是根據類創建出來的一個個具體的“對象”&#xff0c;每個對象都擁有相同的方法&#xff0c;…

解決sublime里面的vue高亮的問題

下載插件文件&#xff1a;https://github.com/vuejs/vue-syntax-highlight 直接在官網下載放在安裝時候的packages目錄下&#xff08;sublime text3\Sublime Text3\Data\Packages&#xff09; 在Packages文件夾下新建一個vue的文件&#xff0c;把第一步下載的文件復制進去 subl…

python矩形填充顏色_在Python中找到所有用0填充的矩形

假設我們有一個二進制2D矩陣&#xff0c;現在我們必須找到所有用0填充的矩形的起點和終點。我們必須牢記&#xff0c;矩形是分開的&#xff0c;彼此之間不接觸&#xff0c;但是它們可以接觸陣列邊界。僅包含單個元素的矩形也是可能的。所以&#xff0c;如果輸入像-101110111011…

python concat_python中merge、concat用法

轉載&#xff1a;https://blog.csdn.net/ly_ysys629/article/details/73849543 參考&#xff1a;https://blog.csdn.net/stevenkwong/article/details/52540605 數據規整化&#xff1a;合并、清理、過濾 pandas和python標準庫提供了一整套高級、靈活的、高效的核心函數和算法將…

Vue使用axios無法讀取data的解決辦法

今天發現Vue中使用了axios后&#xff0c;then方法中無法讀取到data中的數據了&#xff0c;總是提示 Cannot set property xxx of undefined 上網找了一圈后發現了一下解決方法。 解決辦法1&#xff1a; methods:{tap:function(){var selfthis;axios.get(xxxxxx).then(function(…

設置博客園標題樣式

1.向博客園申請js權限 我們需要進入博客園自定義博客模板的頁面&#xff0c;向博客園管理團隊申請頁面運行js的權限。【博客園】->【設置】->【博客設置】&#xff0c;點擊頁面上的js權限申請&#xff0c;然后填寫申請的理由&#xff0c;耐心等幾分鐘&#xff0c;再刷新一…

Spring 3.1 –從數據庫加載XML配置的屬性

Spring使通過其PropertyPlaceholderConfigurer和&#xff08;Spring 3.1之前&#xff09;PropertySourcesPlaceholderConfigurer&#xff08;Spring 3.1&#xff09;從屬性文件中獲取的值易于注入。 這些類實現了BeanFactoryPostProcessor接口&#xff0c;該接口使它們能夠在初…

如何判斷PHP 是線程安全還是非線程安全的

什么是線程安全與非線程安全&#xff1f; 線程安全就是在多線程環境下也不會出現數據不一致&#xff0c;而非線程安全就有可能出現數據不一致的情況。 線程安全由于要確保數據的一致性&#xff0c;所以對資源的讀寫進行了控制&#xff0c;換句話說增加了系統開銷。所以在單線程…

關聯查詢mysql_《MySQL數據庫》關聯查詢

原標題&#xff1a;《MySQL數據庫》關聯查詢一、關聯查詢1、概念在查詢數據時&#xff0c;所需要的數據不只在一張表中&#xff0c;可能在兩張或多張表中。這個時候&#xff0c;需要同時操作這些表來查詢數據&#xff0c;即關聯查詢。關聯查詢所涉及到的表與表之間都會存在有關…

python語言語塊句的標記_《自然語言處理理論與實戰》

編輯推薦 1.講解自然語言處理的理論 2.案例豐富&#xff0c;實戰性強 3.適合自然語言處理學習的入門者 內容提要 自然語言處理是什么&#xff1f;誰需要學習自然語言處理&#xff1f;自然語言處理在哪些地方應用&#xff1f;相關問題一直困擾著不少初學者。針對這一情況&#x…

NOIP2017年11月9日賽前模擬

最后一次NOIP模擬了 題目1&#xff1a;回文數字 Tom 最近在研究回文數字。  假設 s[i] 是長度為 i 的回文數個數&#xff08;不含前導0&#xff09;&#xff0c;則對于給定的正整數 n 有&#xff1a; 以上等式中最后面的括號是布爾表達式&#xff0c;Tom 想知道S[n] mod 2333…

height百分比失效

heigh:100%失效 解決方案&#xff1a; 第一種 html, body { height: 100%; } 第二種 div { height: 100%; position: absolute; } 非定位元素的寬高百分比計算不會將 padding 計算在內&#xff0c;而定位元素會計算在內。 利用這個特性可以實現圖片左右半區點擊分別上一張圖…