JAVA中用进程条显示线程执行进度

JAVA中用进程条显示线程执行进度,第1张

线程时,会牵扯到swing的单线程机制以及线程不安全。

派发线程以外的线程如何更新swing。

swing设计时是单线程的,同时又是线程不安全的,它并不和主程序在一个线程中,而是自己单独创建的一个线程中,因此在这个让森线程以外的任何线程都不是它的派发线程,如果此时要在主程序或是swing本身线程以外的线程来更新swing的值,就是不安全的,不允许这样做。

但是大多数情况下,我们更新进度条等等这类swing组件的值恰好都是在它的派发线程以外的线程中执行,那么该怎么办呢?芦滑渗?

呵呵,java提供了一个机制:

SwingUtilities.invokeLater(建议好好看看这个,多线程编程用它的地方多着呢)

SwingUtilities.invokeLater的机制网上文章很多,在这就不说了。

解决了这个问题,接下来就容易了。

首先,创建进度条对象,设置相关属性,把它添加到容器中,这个就不用说了。

进度条最关键的问题是:如何获取更新值?

否则会出现,你的任务先执行,然后才执行进度条,两者没有同步。

举个例子:

你要读一个文件,那么获取这个文件长度,设置进度条的最大值为文件长度(把文件长度Long转化为Integer);

当执行文件读写 *** 作时,每次读取一个buffersize(你设置的缓冲大小),让value += count;count记录每读写文件一次,读写的字陪脊节数目

value的最终值是文件长度。用progressbar.setvalue(value)来更新进度条的值,注意,前面已经说过,不能直接在派发线程以外的线程更新swing组件,因此这时进度条并没有更新,不会在界面中反映出来,还是停止不动。因该这样更新: SwingUtilities.invokeLater(progressUpdate)就可以了。

progressUpdate--------------

Runnable progressUpdate = new Runnable() {

public void run() {

pb.setValue(value)

count = (double)100*progress/fileLength

taskOutput.append(String.format(

"Completed %f%% of task.\n", count))

}

开始页面:start.jsp

<%@ page contentType="text/htmlcharset=GBK" %>

<% session.removeAttribute("task")%>

<jsp:useBean id="task" scope="session" class="progress.TaskBean"/>

<% task.setRunning(true)%>

<% new Thread(task).start()%>

<jsp:forward page="status.jsp"/>

状态页面:status.jsp

<%@ page contentType="text/htmlcharset=GBK" %>

<jsp:useBean id="task" scope="session" class="progress.TaskBean"/>

<HTML>

<HEAD>

<TITLE>JSP进度条</TITLE>

<% if (task.isRunning()) { %>

<script type="" LANGUAGE="JavaScript">

setTimeout("location='status.jsp'", 1000)

</script>

<% } %>

</HEAD>

<bODY bgcolor="">

<H1 ALIGN="CENTER">JSP进度条</H1>

<H2 ALIGN="CENTER">

结果: <%= task.getResult() %><BR>

<% int percent = task.getPercent()%>

<%= percent %>%

</H2>

<TABLE WIDTH="60%" ALIGN="CENTER"

CELLPADDING=0 CELLSPACING=2>

<TR>

<% for (int i = 10i <= percenti += 10) { %>

<TD WIDTH="10%" height="10" BGCOLOR="red"></TD>

<% } %>

<% for (int i = 100i >percenti -= 10) { %>

<TD WIDTH="10%"></TD>

<% } %>

</TR>

</TABLE>谨斗

<TABLE WIDTH="100%" BORDER=0 CELLPADDING=0 CELLSPACING=0>

<TR>

<TD ALIGN="CENTER">

<% if (task.isRunning()) { %>

正在执行

<% } else { %>

<% if (task.isCompleted()) { %>

完成

<% } else if (!task.isStarted()) { %>

尚未开始

<% } else { %>

已停止

<% } %>

<% } %>

</TD>弯晌裤

</TR>

<TR>

<TD ALIGN="CENTER">

<BR>

<% if (task.isRunning()) { %>

<FORM METHOD="GET" ACTION="stop.jsp">

<INPUT TYPE="SUBMIT" ="停止">

</FORM>

<% } else { %>

<FORM METHOD="GET"埋简 ACTION="start.jsp">

<INPUT TYPE="SUBMIT" ="开始">

</FORM>

<% } %>

</TD>

</TR>

</TABLE>

</BODY></HTML>

停止页面:stop.jsp

<%@ page contentType="text/htmlcharset=GBK" %>

<jsp:useBean id="task" scope="session" class="progress.TaskBean"/>

<% task.setRunning(false)%>

<jsp:forward page="status.jsp"/>

业务逻辑bean:TaskBean.java

package progress

import java.io.Serializable

public class TaskBean

implements Runnable, Serializable {

private int counter

private int sum

private boolean started

private boolean running

private int sleep

public TaskBean() {

counter = 0

sum = 0

started = false

running = false

sleep = 100

}

protected void work() {

try {

Thread.sleep(sleep)

counter++

sum += counter

}

catch (InterruptedException e) {

setRunning(false)

}

}

public synchronized int getPercent() {

return counter

}

public synchronized boolean isStarted() {

return started

}

public synchronized boolean isCompleted() {

return counter == 100

}

public synchronized boolean isRunning() {

return running

}

public synchronized void setRunning(boolean running) {

this.running = running

if (running) {

started = true

}

}

public synchronized Object getResult() {

if (isCompleted()) {

return new Integer(sum)

}

else {

return null

}

}

public void run() {

try {

setRunning(true)

while (isRunning() &&!isCompleted()) {

work()

}

}

finally {

setRunning(false)

}

}

}

你的 action 事件可以放在一个新线程中运行,不要阻挡 Swing 画图。

Swing 对事件的响应都是放在一个叫事件派发的线程中去做睁隐高的,如携吵果你的事件响应监听器本身在被事件派发线程调用时你做的事件太花时间了(比如我们来个无限循环啥的)我们就应该把这个 actionPerformed 方法中的事情放在一个新开的线程中去做:

public void actionPerformed(final ActionEvent e) {

new Thread() {

public void run() { // 你的事情都放在这里处理 }

}.start() // 开启一个悉尺新线程来处理,它将不再阻挡 Swing 事件派发线程去绘图。

}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12514942.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-26
下一篇 2023-05-26

发表评论

登录后才能评论

评论列表(0条)

保存