java swing thread_Java Swing thread 工作原理

public static void showWaitWithProcessBar(final Window

frame, String msg, final Runnable runnable, ProgressBarData

getProgress) {

final JWindow msgFrame = new JWindow(frame);

JProgressBar progressBar = new JProgressBar();

makeMsgFrameWithProcessBar(frame, msgFrame, msg,

progressBar);

Thread myThread = new Thread(new Runnable() {

@Override

public void run() {

RuntimeException e = null;

try {

ExecutorService executor =

Executors.newSingleThreadExecutor();

executor.execute(runnable);

executor.shutdown();

while (!executor.isTerminated()) {

ThreadUtil.sleep(200);

SwingUtilities.invokeLater(new Runnable() {

@Override

public

void run() {

msgFrame.setLocationRelativeTo(frame);

progressBar.setValue(getProgress.getProgress());

progressBar.updateUI();

}

});

}

if ((frame instanceof JDialog) & executor.isTerminated() &

(getProgress.getProgress() == 100 )) {

SwingUtilities.invokeLater(new

Runnable() {

@Override

public void run() {

frame.dispose();

}

});

}

}

catch(RuntimeException exception) {

e = exception;

}

finally {

msgFrame.setVisible(false);

msgFrame.dispose();

frame.repaint();

if(e != null)

throw e;

}

}

});

public static void showWaitWithProcessBar(final Window frame,

String msg, final Runnable runnable, ProgressBarData getProgress)

{

final JWindow msgFrame = new JWindow(frame);

JProgressBar progressBar = new JProgressBar();

makeMsgFrameWithProcessBar(frame, msgFrame, msg,

progressBar);

Thread myThread = new Thread(new Runnable() {

@Override

public void run() {

RuntimeException e = null;

try {

ExecutorService executor =

Executors.newSingleThreadExecutor();

executor.execute(runnable);

executor.shutdown();

while (!executor.isTerminated()) {

ThreadUtil.sleep(200);

SwingUtilities.invokeLater(new Runnable() {

@Override

public void run() {

msgFrame.setLocationRelativeTo(frame);

progressBar.setValue(getProgress.getProgress());

progressBar.updateUI();

}

});

}

if ((frame instanceof JDialog) & executor.isTerminated() &

(getProgress.getProgress() == 100 )) {

SwingUtilities.invokeLater(new

Runnable() {

@Override

public

void run() {

frame.dispose();

}

});

}

}

catch(RuntimeException exception) {

e = exception;

}

finally {

msgFrame.setVisible(false);

msgFrame.dispose();

frame.repaint();

if(e != null)

throw e;

}

}

});

对于以上这个Java的代码,函数showWaitWithProcessBar是在Swing组件的actionPerformed函数中调用的,它的参数runnable是一个费时的操作。如何理解这个函数的实现,需要理解Swing的实现机制:Swing是一个单线程执行的,也就是其界面组件的创建绘制更新都是单线程顺序执行的,如果有多个线程都更新界面的话,其结果是不可预知的。一个典型的Swing程序,参与的线程至少有如下几个:主线程,EDT事件分发处理线程,事件捕获线程;事件捕获线程用户不需要参与,它负责捕获各种信号,如鼠标点击,键盘输入等等信号,并且把这些信号送入一个事件队列中,而EDT线程则是从这个队列中取出信号并且找到其相应的处理函数执行之,然后再处理下一个世纪。从中可以看出Swing程序只有一个事件队列,按先进先出处理。

a4c26d1e5885305701be709a3d33442f.png

各种Swing组件的ActionPerformed函数其实是在EDT线程中执行的,如果在这些函数中放置了费时的操作,就会导致Swing界面不能及时响应用户的各种输入。另外SwingUtilities.

invokeAndWait(), SwingUtilities. invokeLater()这两个函数的一个共同的作用就是把它们的操作包装成一个事件放入事件队列中,让EDT去执行相关的动作,这样当在其他的线程中,如果需要访问Swing组件时,就需要用到这两个函数。

回到上面代码,由于showWaitWithProcessBar是在swing组件的ActionPerformed函数调用的,所以它的执行是在EDT线程中,由于这个函数传入的参数runnable是一个费时的操作,所以runnable的执行不能在EDT线程中,所以需要生成一个新的线程来运行,这里用线程池Executors.newSingleThreadExecutor来处理,同时还需要有一个线程用来查询这个runnable操作处理的进度,然后更新到Swing的进度条上,所以这里使用new

一个Thread操作new

Thread(new Runnable()来查询处理的进度,并且使用SwingUtilities.invokeLater让进度条的更新操作回到EDT线程中执行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值