日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

zk ui_高级ZK:异步UI更新和后台处理–第2部分

發布時間:2023/12/3 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 zk ui_高级ZK:异步UI更新和后台处理–第2部分 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

zk ui

介紹

在第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靜態方法。
  • 將非線程安全參數傳遞給后臺任務。 例如,傳遞一個可變的列表,該可變的列表可能會在任務運行時由編寫者修改(總是制作可變集合的副本!)。
  • 在事件中傳遞非線程安全的結果數據。 例如,在結果事件中傳遞列表,而稍后將在任務中修改列表(始終創建可變集合的副本!)。
  • 在桌面中訪問非線程安全的方法。 即使您可以在后臺任務中訪問桌面,大多數桌面方法也不是線程安全的。 例如,不能保證調用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

zk ui

總結

以上是生活随笔為你收集整理的zk ui_高级ZK:异步UI更新和后台处理–第2部分的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。