简体   繁体   English

为什么java swing不允许从ExecutorService Thread进行更改

[英]Why java swing does not allow changes from an ExecutorService Thread

I have a problem about my java GUI management. 我的java GUI管理有问题。 I'm making an updater but when i'm trying to edit some JText or JProgressbar from an ExecutorService Thread, nothing.. 我正在制作更新程序但是当我尝试从ExecutorService线程编辑一些JText或JProgressbar时,没有...

Why is it broken ? 它为什么坏了? This is my ControllerManager: 这是我的ControllerManager:

public class UpdateManager extends AppManager {
    private final List<Controller> controllers;
    @Getter private final ExecutorService worker;
    @Getter private final UserInterface form;
    private boolean isEnd;

    public UpdateManager() {
        this.controllers = new ArrayList<>();
        this.form = new Form(this);
        this.worker = Executors.newCachedThreadPool();
    }

    @Override
    public void start(Controller... controllers) {
        form.initialize();

        this.controllers.addAll(Arrays.asList(controllers));

        for(Controller controller: controllers)
            controller.start();
    }

    @Override
    public void end(boolean dispose) {
        if(isEnd) return;

        for(Controller controller: controllers)
            controller.end();

        if(dispose) form.dispose();
        isEnd = true;
    }
}

And here is an example when i'm trying to change some labels: 这是一个例子,当我试图改变一些标签:

/**
 * Created by romain on 17/05/2015.
 */
public class ReleaseController implements Controller {
    private final AppManager manager;
    @Getter private final LinkedBlockingDeque<URL> files;
    private Future<?> future;
    private final SerializedObject<SerializedReleases> serializedReleases;
    private final SerializedObject<Integer> serializedRelease, serializedTimestamp;

    public ReleaseController(AppManager manager) {
        this.manager = manager;
        this.files = new LinkedBlockingDeque<>();
        this.serializedReleases = SerializedObjectImpl.create(FileUtils.path("releases", "releases.dat"), true, null);
        this.serializedRelease = SerializedObjectImpl.create(FileUtils.path("swtour", "release.int"), false, 0);
        this.serializedTimestamp = SerializedObjectImpl.create(FileUtils.path("swtour", "timestamp.int"), false, 0);
    }

    /**
     * TODO: checking local files
     */
    @Override
    public void start() {
        this.future = manager.getWorker().submit(new Runnable() {
            @Override
            public void run() {
                int release = serializedRelease.get();
                int serverRelease = serializedReleases.get().lastRelease(AppUtils.OS);
                int result = serverRelease - release;

                if(result == 0 || result < 0) {
                    manager.getForm().alreadyUpdated(); //HERE
                    return;
                }

                for(int i=release+1;i<serverRelease;i++) {
                    try {
                        files.addLast(new URL(
                                FileUtils.path(Main.SERVER, "releases", AppUtils.OS.toString(), i + ".zip")));
                    } catch(Exception e) {
                        System.out.println(e.getMessage());
                    }
                }

                serializedRelease.setObject(serverRelease).write();
                serializedTimestamp.setObject((int)System.currentTimeMillis()).write();
            }
        });
    }

    @Override
    public void end() {
        if(future != null && !future.isCancelled())
            future.cancel(true);
    }

}

If you saw correctly, it: 如果你看得对,它:

manager.getForm().alreadyUpdated();

Modifies my GUI : 修改我的GUI:

public void alreadyUpdated() {
        content.getFirstLine().setText("");
        content.getSecondLine().setText("Your client is already up-to-date!");
        content.getPlayButton().setEnabled(true);
}

but nothing.. My gui is not changed ! 但没什么..我的gui没变! Thank you 谢谢

There are two problems with attempting to update a Swing data structure from another thread: 尝试从另一个线程更新Swing数据结构有两个问题:

  1. Swing is not designed to be multi-thread safe. Swing的设计并非多线程安全。 You could corrupt its data structures. 您可能会破坏其数据结构。
  2. There is nothing forcing it to see changes made in another thread. 没有什么可以强迫它看到在另一个线程中进行的更改。 It can be running with values in registers or caches that are not affected by changes to memory. 它可以在不受内存更改影响的寄存器或高速缓存中运行。

As already noted in a comment, you need to use invokeAndWait or invokeLater to make your changes in the Swing event handling thread. 正如在注释中已经指出的那样,您需要使用invokeAndWaitinvokeLater在Swing事件处理线程中进行更改。

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

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