swingworker_使用SwingWorker的Java Swing中的多线程

swingworker

如果要使用Swing用J​​ava编写桌面或Java Web Start程序,您可能会觉得需要通过创建自己的线程在后台运行某些程序。

没有什么可以阻止您在Swing中使用标准的多线程技术,并且需要遵循通常的注意事项。 如果有多个线程访问相同的变量,则需要使用同步方法或代码块(或诸如AtomicInteger或ArrayBlockingQueue之类的线程安全类)。

但是,对于那些粗心的人来说是一个陷阱。 与大多数用户界面API一样,您无法从自己创建的线程更新用户界面。 好吧,正如每个Java本科生都知道的那样,您通常可以 ,但是您不应该。 如果这样做,有时您的程序会运行,而其他时候则无法。

您可以通过使用专门的SwingWorker类来解决此问题。 在本文中,我将向您展示即使您正在使用Thread类,如何使您的程序正常运行,然后我们将继续研究SwingWorker解决方案。

为了演示,我创建了一个Swing程序。

如您所见,它由两个标签和一个开始按钮组成。 此刻,单击开始按钮将调用一个不执行任何操作的处理程序方法。 这是Java代码:

import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import java.util.concurrent.ExecutionException;import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;public class MainFrame extends JFrame {private JLabel countLabel1 = new JLabel('0');private JLabel statusLabel = new JLabel('Task not completed.');private JButton startButton = new JButton('Start');public MainFrame(String title) {super(title);setLayout(new GridBagLayout());countLabel1.setFont(new Font('serif', Font.BOLD, 28));GridBagConstraints gc = new GridBagConstraints();gc.fill = GridBagConstraints.NONE;gc.gridx = 0;gc.gridy = 0;gc.weightx = 1;gc.weighty = 1;add(countLabel1, gc);gc.gridx = 0;gc.gridy = 1;gc.weightx = 1;gc.weighty = 1;add(statusLabel, gc);gc.gridx = 0;gc.gridy = 2;gc.weightx = 1;gc.weighty = 1;add(startButton, gc);startButton.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent arg0) {start();}});setSize(200, 400);setDefaultCloseOperation(EXIT_ON_CLOSE);setVisible(true);}private void start() {}public static void main(String[] args) {SwingUtilities.invokeLater(new Runnable() {@Overridepublic void run() {new MainFrame('SwingWorker Demo');}});}
}

我们将添加一些代码到start()方法中,以响应单击开始按钮而调用。

首先让我们尝试一个普通线程。

private void start() {Thread worker = new Thread() {public void run() {// Simulate doing something useful.for(int i=0; i<=10; i++) {// Bad practicecountLabel1.setText(Integer.toString(i));try {Thread.sleep(1000);} catch (InterruptedException e) {}}// Bad practicestatusLabel.setText('Completed.');}};worker.start();}

实际上,此代码似乎有效(至少对我而言)。 该程序最终看起来像这样:

但是,不建议您这样做。 我们正在从自己的线程中更新GUI,在某些情况下,这肯定会引发异常。

如果要从另一个线程更新GUI,则应使用SwingUtilities安排更新代码在事件分发线程上运行。

下面的代码很好,但是像恶魔一样丑陋。

private void start() {Thread worker = new Thread() {public void run() {// Simulate doing something useful.for(int i=0; i<=10; i++) {final int count = i;SwingUtilities.invokeLater(new Runnable() {public void run() {countLabel1.setText(Integer.toString(count));}});try {Thread.sleep(1000);} catch (InterruptedException e) {}}SwingUtilities.invokeLater(new Runnable() {public void run() {statusLabel.setText('Completed.');}});}};worker.start();}

当然,必须做些什么使我们的代码更优雅?

SwingWorker班

SwingWorker是使用Thread class (专门为Swing设计)的替代方法。 这是一个抽象类,它带有两个模板参数,这使它看起来非常凶猛,并使大多数人无法使用它。 但是实际上,它并不像看起来那样复杂。

让我们看一些仅运行后台线程的代码。 对于第一个示例,我们将不会使用任何一个模板参数,因此将它们都设置为Void ,这是Java的等效于原始void类型的类(带有小写的“ v”)。

运行后台任务

通过实现doInBackground方法并调用execute来运行代码,我们可以在后台运行任务。

SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {@Overrideprotected Void doInBackground() throws Exception {// Simulate doing something useful.for (int i = 0; i <= 10; i++) {Thread.sleep(1000);System.out.println('Running ' + i);}return null;}};worker.execute();

请注意, SwingWorker是一件简单的事情,因此,如果我们想再次运行代码,则需要创建另一个SwingWorker ; 您无法重新启动同一个。

很简单,嘿? 但是,如果我们想在运行代码后以某种状态更新GUI,该怎么办? 您无法从doInBackground更新GUI,因为它不在主事件分配线程中运行。

但是有一个解决方案。 我们需要利用第一个模板参数。

线程完成后更新GUI

我们可以通过从doInBackground()返回一个值,然后覆盖过去的done()来更新GUI,从而可以安全地更新GUI。 我们使用get()方法检索从doInBackground()返回的值

因此,第一个模板参数确定doInBackground()get()的返回类型。

SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {@Overrideprotected Boolean doInBackground() throws Exception {// Simulate doing something useful.for (int i = 0; i <= 10; i++) {Thread.sleep(1000);System.out.println('Running ' + i);}// Here we can return some object of whatever type// we specified for the first template parameter.// (in this case we're auto-boxing 'true').return true;}// Can safely update the GUI from this method.protected void done() {boolean status;try {// Retrieve the return value of doInBackground.status = get();statusLabel.setText('Completed with status: ' + status);} catch (InterruptedException e) {// This is thrown if the thread's interrupted.} catch (ExecutionException e) {// This is thrown if we throw an exception// from doInBackground.}}};worker.execute();

如果我们要在进行过程中更新GUI怎么办? 这就是第二个模板参数的用途。

从正在运行的线程更新GUI

要从正在运行的线程更新GUI,我们使用第二个模板参数。 我们调用publish()方法来“发布”我们要用来更新用户界面的值(可以是第二个模板参数指定的任何类型)。 然后,我们覆盖process()方法,该方法接收我们发布的值。

实际上process()接收已发布值的列表,因为在实际调用process()之前可能会发布多个值。

在此示例中,我们只是将最新值发布到用户界面。

SwingWorker<Boolean, Integer> worker = new SwingWorker<Boolean, Integer>() {@Overrideprotected Boolean doInBackground() throws Exception {// Simulate doing something useful.for (int i = 0; i <= 10; i++) {Thread.sleep(1000);// The type we pass to publish() is determined// by the second template parameter.publish(i);}// Here we can return some object of whatever type// we specified for the first template parameter.// (in this case we're auto-boxing 'true').return true;}// Can safely update the GUI from this method.protected void done() {boolean status;try {// Retrieve the return value of doInBackground.status = get();statusLabel.setText('Completed with status: ' + status);} catch (InterruptedException e) {// This is thrown if the thread's interrupted.} catch (ExecutionException e) {// This is thrown if we throw an exception// from doInBackground.}}@Override// Can safely update the GUI from this method.protected void process(List<Integer> chunks) {// Here we receive the values that we publish().// They may come grouped in chunks.int mostRecentValue = chunks.get(chunks.size()-1);countLabel1.setText(Integer.toString(mostRecentValue));}};worker.execute();

我希望您喜欢这个非常有用的SwingWorker类的介绍。

在我的网站Cave of Programming中 ,您可以找到更多的教程,包括完整的免费视频教程以及有关Swing,Android和Servlets的多线程课程。

参考:来自Java出现日历博客的JCG合作伙伴 John Purcell的SwingWorker中的Java Swing中的多线程 。

翻译自: https://www.javacodegeeks.com/2012/12/multi-threading-in-java-swing-with-swingworker.html

swingworker

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/349555.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

指定端口传输_一段话告诉你什么是端口

1、端口的含义端口是指接口电路中的一些寄存器&#xff0c;这些寄存器分别用来存放数据信息、控制信息和状态信息&#xff0c;相应的端口分别称为数据端口、控制端口和状态端口。电脑运行的系统程序&#xff0c;其实就像一个闭合的圆圈&#xff0c;但是电脑是为人服务的&#x…

loop在python中什么意思_python中迭代什么意思

1、迭代&#xff1a; 迭代是通过重复执行的代码处理相似的数据集的过程&#xff0c;并且本次迭代的处理数据要依赖上一次的结果继续往下做&#xff0c;上一次产生的结果为下一次产生结果的初始状态&#xff0c;如果中途有任何停顿&#xff0c;都不能算是迭代。例如&#xff1a;…

使用Spring Data的Apache Ignite

Spring Data提供了一种统一而简单的方法来访问不同类型的持久性存储&#xff0c;关系数据库系统和NoSQL数据存储。 它位于JPA之上&#xff0c;添加了另一层抽象并定义了基于标准的设计以在Spring上下文中支持持久层。 Apache Ignite IgniteRepository实现了Spring Data CrudR…

js hover图片放大不遮挡_CSS3+JS 实现放大镜

注意&#xff1a;看懂本文需要&#xff1a;懂中文 &#xff1a;)学习过 JavaScript 和 css代码较长&#xff0c;框框可左右滑动哦您的观看和点赞是对本公众号最大力的支持 ~~原文链接&#xff1a;https://blog.csdn.net/qq_43624878/article/details/110197749 CSS3JS完美实现放…

python装饰器class_Python中的各种装饰器详解

Python装饰器&#xff0c;分两部分&#xff0c;一是装饰器本身的定义&#xff0c;一是被装饰器对象的定义。 一、函数式装饰器&#xff1a;装饰器本身是一个函数。 1.装饰函数&#xff1a;被装饰对象是一个函数 [1]装饰器无参数&#xff1a; a.被装饰对象无参数&#xff1a; &g…

odoo controller 继承

方式一&#xff1a; 继承基类&#xff0c;直接重写方法 from odoo.addons.web.controllers.main import Exportclass PsExport(Export): http.route(/web/export/get_fields, typejson, auth"user") def get_fields(self, model, prefix, parent_name , import_co…

python字符串startswith_Python 字符串 startswith() 使用方法及示例

Python 字符串 startswith() 使用方法及示例如果字符串以指定的前缀(字符串)开头&#xff0c;则startswith()方法将返回True。如果不是&#xff0c;则返回False。startswith()的语法为&#xff1a;str.startswith(prefix[, start[, end]])startswith()参数startswith()方法最多…

odoo连接外部数据库

odoo框架默认的访问时Postgres数据库&#xff0c;但在实际的应用场景中&#xff0c;不可避免的使用到其他数据库&#xff0c;所以有必要研究如何连接其他第三方数据库&#xff0c;这里分享下OCA的相关模块&#xff0c;具体的源代码在这里。 我将第三方的数据库需要连接的情况汇…

整型和bcd的对应关系_微信与多闪之争背后,好友关系链到底是如何窃取的?

这几天从发布到全面推广&#xff0c;多闪已经快速的超越100万用户&#xff0c;迅速占领了appsotre榜首&#xff0c;在七麦数据中也是蝉联第一。但因多闪包括头条产品登录采取都支持【微信第三方登录】。很多用户都反馈是否自己的关系链被多闪、甚至是抖音窃取&#xff0c;并且腾…

线程同步,线程不同步_同步多线程集成测试

线程同步,线程不同步测试线程非常困难&#xff0c;这使得为被测多线程系统编写良好的集成测试非常困难。 这是因为在JUnit中&#xff0c;测试代码&#xff0c;被测对象和任何线程之间没有内置的同步。 这意味着&#xff0c;当您必须为创建并运行线程的方法编写测试时&#xff0…

ehcache 默认大小_简单的使用ehcache

ehcache是一个用Java实现的使用简单&#xff0c;高速&#xff0c;实现线程安全的缓存管理类库&#xff0c;ehcache提供了用内存&#xff0c;磁盘文件存储&#xff0c;以及分布式存储方式等多种灵活的cache管理方案。同时ehcache作为开放源代码项目&#xff0c;采用限制比较宽松…

JS定时器使用,定时定点,固定时刻,循环执行

本文概述&#xff1a;本文主要介绍通过JS实现定时定点执行&#xff0c;在某一个固定时刻执行某个函数的方法。比如说在下一个整点执行&#xff0c;在每一个整点执行&#xff0c;每隔10分钟定时执行的方法。 JavaScript中有两个定时器方法&#xff1a;setTimeout&#xff08;&am…

axios 跨域_当遇到跨域开发时,我们如何处理好前后端配置和请求库封装

我们知道很多大型项目都或多或少的采用跨域的模式开发, 以达到服务和资源的解耦和高效利用. 在大前端盛行的今天更为如此, 前端工程师可以通过nodejs或者Nginx轻松搭建起web服务器.这个时候我们只需要请求后端服务器的接口即可实现系统的业务功能开发.这个过程中会涉及到web页面…

Java数据类型和标识符

在本教程中&#xff0c;我们将了解Java中的数据类型和标识符。 Java语言具有丰富的数据类型实现。 数据类型指定大小和可以存储在标识符中的值的类型。 Java数据类型分为两类&#xff1a; 原始数据类型 非原始数据类型 原始类型 Java定义了八种原始数据类型&#xff1a;字…

哈罗顺风车送到终点吗_没有了顺风车,滴滴“特惠拼车”来了!比拼车更低价,比顺风车更安全吗?...

近日&#xff0c;有网友表示&#xff0c;滴滴出行App内出现了“特惠拼车”功能&#xff0c;据悉&#xff0c;该功能主要给乘客提供长距离拼车出行的优惠折扣。如果拼车价格为44.8元&#xff0c;那“特惠拼车”的价格为30.7元。但是该功能目前还未在上海出现。近日&#xff0c;有…

管理角色认知-工程师到管理者角色发生了哪些变化?

背景 不同等级的管理者需求不同&#xff1b; 管理者需求说明新经理提供管理相关的工具和方法能力层面&#xff0c;术高级经理提升角色认知认知和理解&#xff0c;道&#xff0c;系统通过认知上的改变达到能力和行为上的改善一个人的行为&#xff0c;能力&#xff0c;价值观都源…

axure 小程序 lib_小程序定制开发的步骤有哪些?

经过两年多的微信小程序开发&#xff0c;各种功能应用变得越来越成熟&#xff0c;越来越多的企业和企业正在开发微信小程序用于在线营销。如果您的公司尚未开发成都小程序&#xff0c;它将变得越来越凶猛。在竞争激烈的市场环境中&#xff0c;将失去许多获得和营销客户的机会。…

java 检查打印机状态_爱普生打印机常见故障有哪些 爱普生打印机故障解决方法【详解】...

任何设备在使用一段时间后都会出现一些小问题&#xff0c;打印机也不例外&#xff0c;那么爱普生打印机常见的故障有哪些 &#xff0c;出现问题该怎么解决呢&#xff1f;下面小编就来分享2018爱普生打印机故障解决方法 &#xff0c;一起来看看吧&#xff01;一、故障现象 &a…

eureka 之前的服务如何关闭_干货分享 | 服务注册中心Spring Cloud Eureka部分源码分析...

友情提示&#xff1a;全文13000多文字&#xff0c;预计阅读时间10-15分钟Spring Cloud Eureka作为常用的服务注册中心&#xff0c;我们有必要去了解其内在实现机制&#xff0c;这样出现问题的时候我们可以快速去定位问题。当我们搭建好Eureka Server服务注册中心并启动后&#…

局部变量写在循环内还是外_循环内的局部变量和性能

局部变量写在循环内还是外总览 有时会出现一个问题&#xff0c;即分配一个新的局部变量需要多少工作。 我的感觉一直是&#xff0c;代码已优化到成本为静态的程度&#xff0c;即一次执行&#xff0c;而不是每次运行都执行一次。 最近&#xff0c; Ishwor Gurung建议考虑将一些…