简体   繁体   English

Java中的并发-等待执行完成

[英]Concurrency in Java - wait for execution to be finished

So I am currently doing some work with Multi-Threading in Java and I'm pretty stuck on a, most likely, simple thing. 因此,我目前正在使用Java中的多线程进行一些工作,而我很可能只停留在一件最简单的事情上。

I currently have a JButton that, when pressed invokes the method as follows: 我目前有一个JButton,按下该按钮时,将按如下方式调用该方法:

private void clickTest() throws InterruptedException{
    statOrganizer.incrementHappiness();
    Thread t = new Thread(new Happiness(workspaceHappy));
    t.start();
}

and then takes around 10-30 seconds to complete. 然后大约需要10到30秒才能完成。 During this time however, it is still possible to re-click the JButton so that it messes with how the information is displayed. 但是,在此期间,仍然可以重新单击JButton,以使它与信息的显示方式混淆。

What I want to do is during the time this particular thread is "alive", disable the button so that it is no longer possible to click it(and thus activate this thread once it's already going). 我想做的是在此特定线程“处于活动状态”期间,禁用该按钮,以使其不再可能单击它(因此一旦该线程已经运行就激活它)。 Once the thread is finished, I want to re-enable the button again. 线程完成后,我想再次重新启用该按钮。

The button code just looks like this 按钮代码如下所示

button.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent evt) {
                if (evt.getClickCount() == 1) {
                        try {
                            clickTest();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                }
            }
        });

Disable the button right before starting the thread. 在启动线程之前立即禁用该按钮。 In the thread, at the end, post an event that would re-enable the button (using invokeLater). 最后,在线程中,发布一个事件,该事件将重新启用按钮(使用invokeLater)。

You may also need a cancel option, but that's a separate question. 您可能还需要取消选项,但这是一个单独的问题。

The nice solution for this is to use a glass pane to capture all events and stopping them from propagating to any of your UI elements on the panel under the glass pane. 一个好的解决方案是使用玻璃窗格捕获所有事件,并阻止它们传播到玻璃窗格下面的面板上的任何UI元素。 Of course while you only have one or two, you can call setEnabled(false) on them manually but glass panes give you more flexibility, you'll never have to worry about adding a new element to your UI and forgetting to disable it during background processing. 当然,虽然只有一两个,但您可以手动对其调用setEnabled(false) ,但是玻璃窗格为您提供了更大的灵活性,您无需担心会在UI中添加新元素而忘记在后台禁用它处理。

Probably an overkill for one button though. 不过,对于一个按钮来说可能是过大的杀伤力。

Another, unrelated thing you should consider is the use of Executor s instead of launching threads for background tasks. 您应该考虑的另一件无关的事情是使用Executor而不是为后台任务启动线程。 It results in cleaner and more scalable code. 这样可以产生更干净,更可扩展的代码。

Try the following: 请尝试以下操作:

button.addMouseListener(new MouseAdapter() {
        public void mouseClicked(MouseEvent evt) {
            if (evt.getClickCount() == 1) {
                    try {
                        clickTest();
                        button.setEnabled(false);//this assume 'button' is final
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
            }
        }
    });

Then, modify the run method of your Happiness class: 然后,修改Happiness类的run方法:

public void run()
{

 //your processing code here
 ...

 button.setEnabled(true);
 //reference to button can be passed in constructor of Happiness
 // or access using getter, ... This really depend on your implementation.

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM