簡體   English   中英

在Java 7+中,在EDT之外使用Swing repaint()方法是否仍然安全?

[英]Is the Swing repaint() method still safe to use outside the EDT in Java 7+?

我知道,即使使用Swing的線程模型,從任何線程調用repaint()和其他一些選定的方法也是安全的,但是我最近在評論中告訴我不是這樣。

谷歌發現很多舊的討論說這是安全的,但最近沒什么。 所有過去曾經說過安全的官方參考資料似乎已經消失了,我在各個論壇上發現了一些人討論它是如何不再安全的。

我找不到任何正式的東西來確認它是否存在 - 而且我真的希望看到一些解釋改變邏輯的東西,如果它已被改變的話。 考慮到破壞現有應用程序的風險有多嚴重,刪除它似乎是一個非常奇怪的功能。

我真的在尋找一個官方參考鏈接(即Javadoc,oracle教程或源代碼鏈接),說明這些方法是否可以安全地從任何線程調用。

這里提到這個問題:

在EDT之外安全使用Component.repaint()?

從現已消失的Sun頁面中引用一句話:

以下JComponent方法可以安全地從任何線程調用:repaint(),revalidate()和invalidate()。 repaint()和revalidate()方法將事件派發線程的請求分別調用paint()和validate()。

這符合我的理解,但我現在找不到那個頁面或任何類似的頁面,我看到幾個人的未經證實的謠言說它不再安全。 但另一方面,我找不到任何明確的說這個功能已經改變。

改變筆記

可能有助於解決這個問題的是Oracle關於Swing線程處理變化的官方聲明。 我發現了“Java 7中的更改”頁面,但根本沒有提到它,這些頁面都沒有以任何方式提及線程或EDT:

http://docs.oracle.com/javase/7/docs/technotes/guides/swing/enhancements-7.html

http://docs.oracle.com/javase/7/docs/technotes/guides/awt/enhancements-7.html

這是官方參考

Swing的線程策略

一般來說,Swing不是線程安全的。 除非另有說明,否則必須在事件派發線程上訪問所有Swing組件和相關類。

並且repaint方法不會“以其他方式記錄”。

為了讓您更加放心,除了單個方法的Javadoc之外,您不需要進一步了解最終答案,例如,請參閱Java 6 Javadoc中如何記錄方法的線程安全性。

更新

顯然,需要對規范性規范,描述性技術文章和任何具體實現的細節之間的區別進行更多澄清。 Javadoc所說的是: 不能保證repaint是一種線程安全的方法 順便提一下,Java 7中經常討論的從大多數Swing API中刪除“線程安全”標識的決定就是: 合同的變更,而不是實現。

OpenJDK 7中repaint的具體實現似乎是線程安全的,這與規范給出的保證無關。 依賴於repaint或其他方法的線程安全性的代碼被破壞 ,並且不能保證在所有Java實現上都能正常運行。

正如在AWT和Swing繪畫中所討論的:油漆處理

JComponent.repaint()向組件的RepaintManager注冊異步重繪請求,該組件使用invokeLater()Runnable進行排隊,以便稍后在事件派發線程上處理請求。

這是在連續調用repaint()之間建立先發生關系的必要條件,但不是充分條件。 實際上,您仍然需要同步訪問線程之間共享的任何數據。 如果沒有這個,就無法確保任何可能影響后續調用repaint()更改的可見性。

我會說它仍然是線程安全的。 repaint()方法不會更改任何Swing組件的屬性。

repaint()方法調用RepaintManager。 然后,RepaintManager將(可能)將多個繪制請求組合到一個繪制請求中。 然后它會將油漆請求添加到EDT進行處理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM