diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java index 592d1aa2..4c92ac36 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java @@ -1223,6 +1223,9 @@ public abstract class FlatLaf } private Object getValue( Object key ) { + // use local variable for getters to avoid potential multi-threading issues + List> uiDefaultsGetters = FlatLaf.this.uiDefaultsGetters; + if( uiDefaultsGetters == null ) return null; @@ -1276,8 +1279,9 @@ public abstract class FlatLaf this.scaleSize = scaleSize; } + // using synchronized to avoid exception if invoked at the same time on multiple threads @Override - public Object createValue( UIDefaults table ) { + public synchronized Object createValue( UIDefaults table ) { if( inCreateValue ) throw new IllegalStateException( "FlatLaf: endless recursion in font" ); diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatStressTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatStressTest.java index 58b39a48..da44cba9 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatStressTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatStressTest.java @@ -22,7 +22,9 @@ import java.util.Random; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JFrame; +import javax.swing.JLabel; import javax.swing.SwingUtilities; +import javax.swing.UIManager; import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.FlatLightLaf; @@ -54,6 +56,7 @@ public class FlatStressTest private JComponent createStressTest() { return createComboBoxStressTest(); +// return createGetFontStressTest(); } // for https://github.com/JFormDesigner/FlatLaf/issues/432 @@ -80,4 +83,30 @@ public class FlatStressTest return comboBox; } + + // for https://github.com/JFormDesigner/FlatLaf/issues/456 + @SuppressWarnings( "unused" ) + private JComponent createGetFontStressTest() { + JLabel label = new JLabel( "test" ); + + Runnable runnable = () -> { + for(;;) { + UIManager.getFont( "Label.font" ); + } + }; + + Thread thread1 = new Thread( runnable); + thread1.setDaemon( true ); + thread1.start(); + + Thread thread2 = new Thread( runnable); + thread2.setDaemon( true ); + thread2.start(); + + Thread thread3 = new Thread( runnable); + thread3.setDaemon( true ); + thread3.start(); + + return label; + } }