第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

創(chuàng)建事件調(diào)度線程安全信號量

創(chuàng)建事件調(diào)度線程安全信號量

米琪卡哇伊 2023-10-12 14:49:24
我一直在嘗試創(chuàng)建一個二進制信號量,它能夠安全地阻止在事件調(diào)度線程(EDT)上運行的方法的執(zhí)行,而不會實際阻止線程處理更多事件。乍一看這似乎是不可能的,但 Java 有一些與此相關(guān)的內(nèi)置功能,但我無法完全讓它工作。使用案例目前,如果您從 EDT 顯示模態(tài)擺動對話框,它似乎會阻止 EDT(因為顯示模態(tài)對話框的方法在對話框關(guān)閉之前不會繼續(xù)到下一行),但實際上有一些問題-hood 魔法,使 EDT 進入一個新的事件循環(huán),該循環(huán)將繼續(xù)調(diào)度事件,直到模式對話框關(guān)閉。我的團隊目前的應用程序正在非常緩慢地從 swing 遷移到 JavaFX(這是一個有點棘手的過渡),并且我希望能夠以與顯示 swing 模態(tài)對話框相同的方式從 AWT 事件調(diào)度線程顯示模態(tài) JavaFX 對話框。似乎擁有某種 EDT 安全信號量就可以滿足這個用例,并且可能在以后的其他用途中派上用場。方法java.awt.EventQueue.createSecondaryLoop()是一種創(chuàng)建SecondaryLoop對象的方法,然后您可以使用該對象來啟動新的事件處理循環(huán)。當您調(diào)用 時SecondaryLoop.enter(),調(diào)用將在處理新的事件循環(huán)時阻塞(請注意,調(diào)用會阻塞,但線程不會阻塞,因為它正在事件處理循環(huán)中繼續(xù))。新的事件循環(huán)將繼續(xù),直到您調(diào)用為止SecondaryLoop.exit()(這并不完全正確,請參閱我的相關(guān) SO 問題)。因此,我創(chuàng)建了一個信號量,其中阻塞調(diào)用會導致等待正常線程的鎖存器,或者進入 EDT 的輔助循環(huán)。每個對 acquire 的阻塞調(diào)用還會添加一個在釋放信號量時調(diào)用的解鎖操作(對于普通線程,它只是遞減鎖存器,對于 EDT,它退出輔助循環(huán))。這是我的代碼:import java.awt.EventQueue;import java.awt.SecondaryLoop;import java.awt.Toolkit;import java.util.Stack;import java.util.concurrent.CountDownLatch;import java.util.concurrent.Semaphore;@SuppressWarnings("serial")public class EventDispatchThreadSafeBinarySemaphore extends Semaphore{    /** Operations used to unblock threads when a semaphore is released.     * Must be a stack because secondary loops have to be exited in the     * reverse of the order in which they were entered in order to unblock     * the execution of the method that entered the loop.     */    private Stack<Runnable> releaseOperations = new Stack<>();    private boolean semaphoreAlreadyAcquired = false;    public EventDispatchThreadSafeBinarySemaphore() {        super(0);    }
查看完整描述

1 回答

?
撒科打諢

TA貢獻1934條經(jīng)驗 獲得超2個贊

使用 aSemaphore很可能不是正確的方法。您想要的是進入嵌套事件循環(huán),而不是使用阻塞機制。從閱讀 API 來看,你似乎把事情過于復雜化了。同樣,您所需要的只是在一個 UI 線程上進入嵌套事件循環(huán),然后在另一個 UI 線程完成其工作后退出該循環(huán)。我相信以下內(nèi)容可以滿足您的要求:


import java.awt.EventQueue;

import java.awt.SecondaryLoop;

import java.awt.Toolkit;

import java.util.Objects;

import java.util.concurrent.atomic.AtomicReference;

import java.util.function.Supplier;

import javafx.application.Platform;

import javax.swing.SwingUtilities;


public class Foo {


    public static <T> T getOnFxAndWaitOnEdt(Supplier<? extends T> supplier) {

        Objects.requireNonNull(supplier, "supplier");

        if (!EventQueue.isDispatchThread()) {

            throw new IllegalStateException("current thread != EDT");

        }


        final SecondaryLoop loop = Toolkit.getDefaultToolkit()

                .getSystemEventQueue()

                .createSecondaryLoop();

        final AtomicReference<T> valueRef = new AtomicReference<>();


        Platform.runLater(() -> {

            valueRef.set(supplier.get());

            SwingUtilities.invokeLater(loop::exit);

        });

        loop.enter();


        return valueRef.get();

    }


    public static <T> T getOnEdtAndWaitOnFx(Supplier<? extends T> supplier) {

        Objects.requireNonNull(supplier, "supplier");

        if (!Platform.isFxApplicationThread()) {

            throw new IllegalStateException(

                    "current thread != JavaFX Application Thread");

        }


        final Object key = new Object();

        final AtomicReference<T> valueRef = new AtomicReference<>();


        SwingUtilities.invokeLater(() -> {

            valueRef.set(supplier.get());

            Platform.runLater(() -> Platform.exitNestedEventLoop(key, null));

        });

        Platform.enterNestedEventLoop(key);


        return valueRef.get();

    }


}

JavaFX 9 中添加了和方法,盡管 JavaFX 8 中也有等效的內(nèi)部方法。使用的原因是因為在 lambda 表達式內(nèi)部使用時,局部變量必須是 Final 或有效的 Final Platform#enterNestedEventLoop。然而,由于通知單獨線程的方式,我不認為 和方法提供的易變性語義是嚴格需要的,但我使用了這些方法以防萬一。Platform#exitNestedEventLoopAtomicReference#get()#set(T)AtomicReference


以下是使用上述內(nèi)容從事件調(diào)度線程顯示模式 JavaFX 對話框的示例:


Optional<T> optional = Foo.getOnFxAndWaitOnEdt(() -> {

    Dialog<T> dialog = new Dialog<>();

    // configure dialog...

    return dialog.showAndWait();

});

上述實用程序方法用于從事件調(diào)度線程到JavaFX 應用程序線程進行通信,反之亦然。這就是為什么需要輸入嵌套事件循環(huán),否則 UI 線程之一將必須阻塞,從而凍結(jié)關(guān)聯(lián)的 UI。如果您位于非 UI 線程上并且需要在等待結(jié)果時在 UI 線程上運行操作,則解決方案要簡單得多:


// Run on EDT

T result = CompletableFuture.supplyAysnc(/*Supplier*/, SwingUtilities::invokeLater).join();


// Run on FX thread

T result = CompletableFuture.supplyAsync(/*Supplier*/, Platform::runLater).join();

調(diào)用join()將阻塞調(diào)用線程,因此請確保不要從任一 UI 線程調(diào)用該方法。


查看完整回答
反對 回復 2023-10-12
  • 1 回答
  • 0 關(guān)注
  • 148 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號