高级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.mzph.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;而定位元素会计算在内。 利用这个特性可以实现图片左右半区点击分别上一张图…