【发布时间】:2014-08-11 21:39:35
【问题描述】:
Java Swing 教程使用 SwingUtilities.invokeLater 创建 GUI(如 here)。解释了为什么这样做here - 大多数 Swing 对象不是线程安全的。另一方面,我见过的大多数 JRuby Swing 示例只是设置了脚本中可见的顶部框架(例如 here - 存档中的“guis”目录)。
问题是,在 JRuby 脚本中创建应用程序顶部框架时,我是否应该遵循使用 SwingUtilities.invokeLater() 的 Java 模式?
我有两个 JRuby 脚本,一个使用 SwingUtilities.invokeLater(),一个不使用:
java_import javax.swing.JFrame
java_import javax.swing.SwingUtilities
java_import java.awt.Dimension
java_import javax.swing.JButton
JavaThread = java.lang.Thread
class TopFrame < JFrame
def initialize
super
init_components()
pack()
set_visible(true)
puts '----------------------------------------'
puts 'In JFrame constructor:'
puts "Thread name: #{JavaThread.current_thread.name}"
puts "Is event dispatch thread: #{SwingUtilities.event_dispatch_thread?}"
JavaThread.current_thread.thread_group.list
end
def init_components()
set_default_close_operation(JFrame::EXIT_ON_CLOSE)
set_preferred_size(Dimension.new(400, 300))
button = JButton.new('Button')
button.add_action_listener do |event|
puts '----------------------------------------'
puts 'In action listener:'
puts "Thread name: #{JavaThread.current_thread.name}"
puts "Is event dispatch thread: #{SwingUtilities.event_dispatch_thread?}"
JavaThread.current_thread.thread_group.list
end
get_content_pane.add(button)
end
end
puts '----------------------------------------'
puts 'Before SwingUtilties.invokeLater():'
puts "Thread name: #{JavaThread.current_thread.name}"
puts "Is event dispatch thread: #{SwingUtilities.event_dispatch_thread?}"
JavaThread.current_thread.thread_group.list
SwingUtilities.invoke_later do
TopFrame.new
end
puts '----------------------------------------'
puts 'After SwingUtilities.invokeLater():'
puts "Thread name: #{JavaThread.current_thread.name}"
puts "Is event dispatch thread: #{SwingUtilities.event_dispatch_thread?}"
JavaThread.current_thread.thread_group.list
输出是:
----------------------------------------
Before SwingUtilties.invokeLater():
Thread name: main
Is event dispatch thread: false
java.lang.ThreadGroup[name=main,maxpri=10]
Thread[main,5,main]
Thread[Ruby-0-JIT-1,1,main]
java.lang.ThreadGroup[name=Ruby Threads#11483240,maxpri=10]
----------------------------------------
After SwingUtilities.invokeLater():
Thread name: main
Is event dispatch thread: false
java.lang.ThreadGroup[name=main,maxpri=10]
Thread[main,5,main]
Thread[Ruby-0-JIT-1,1,main]
Thread[AWT-EventQueue-0,6,main]
java.lang.ThreadGroup[name=Ruby Threads#11483240,maxpri=10]
----------------------------------------
In JFrame constructor:
Thread name: AWT-EventQueue-0
Is event dispatch thread: true
java.lang.ThreadGroup[name=main,maxpri=10]
Thread[AWT-EventQueue-0,6,main]
Thread[DestroyJavaVM,5,main]
java.lang.ThreadGroup[name=Ruby Threads#11483240,maxpri=10]
----------------------------------------
In action listener:
Thread name: AWT-EventQueue-0
Is event dispatch thread: true
java.lang.ThreadGroup[name=main,maxpri=10]
Thread[AWT-EventQueue-0,6,main]
Thread[DestroyJavaVM,5,main]
java.lang.ThreadGroup[name=Ruby Threads#11483240,maxpri=10]
在 SwingUtilities.invokeLater() 被调用之前 EDT 不存在 SwingUtilities.invokeLater() 之后 EDT 存在并且它与当前线程不同。在 JFrame 构造函数和 JButton 动作事件监听器中 EDT 是当前线程。
另一个脚本没有使用 SwingUtilities.invokeLater():
java_import javax.swing.JFrame
java_import javax.swing.SwingUtilities
java_import java.awt.Dimension
java_import javax.swing.JButton
JavaThread = java.lang.Thread
puts '----------------------------------------'
puts 'Before JFrame.new():'
puts "Thread name: #{JavaThread.current_thread.name}"
puts "Is event dispatch thread: #{SwingUtilities.event_dispatch_thread?}"
JavaThread.current_thread.thread_group.list
frame = JFrame.new()
frame.set_default_close_operation(JFrame::EXIT_ON_CLOSE)
frame.set_preferred_size(Dimension.new(400, 300))
button = JButton.new('Button')
button.add_action_listener do |event|
puts '----------------------------------------'
puts 'In action listener:'
puts "Thread name: #{JavaThread.current_thread.name}"
puts "Is event dispatch thread: #{SwingUtilities.event_dispatch_thread?}"
JavaThread.current_thread.thread_group.list
end
frame.get_content_pane.add(button)
frame.pack()
puts '----------------------------------------'
puts 'Before JFrame.setVisible():'
puts "Thread name: #{JavaThread.current_thread.name}"
puts "Is event dispatch thread: #{SwingUtilities.event_dispatch_thread?}"
JavaThread.current_thread.thread_group.list
frame.set_visible(true)
输出是:
----------------------------------------
Before JFrame.new():
Thread name: main
Is event dispatch thread: false
java.lang.ThreadGroup[name=main,maxpri=10]
Thread[main,5,main]
Thread[Ruby-0-JIT-1,1,main]
java.lang.ThreadGroup[name=Ruby Threads#11483240,maxpri=10]
----------------------------------------
Before JFrame.setVisible():
Thread name: main
Is event dispatch thread: false
java.lang.ThreadGroup[name=main,maxpri=10]
Thread[main,5,main]
Thread[Ruby-0-JIT-1,1,main]
Thread[AWT-EventQueue-0,6,main]
java.lang.ThreadGroup[name=Ruby Threads#11483240,maxpri=10]
----------------------------------------
In action listener:
Thread name: AWT-EventQueue-0
Is event dispatch thread: true
java.lang.ThreadGroup[name=main,maxpri=10]
Thread[AWT-EventQueue-0,6,main]
Thread[DestroyJavaVM,5,main]
java.lang.ThreadGroup[name=Ruby Threads#11483240,maxpri=10]
EDT 是在 JFrame 构造函数不是当前线程之后创建的。在 JButton 事件监听器中 EDT 是当前线程。
【问题讨论】:
标签: java multithreading swing jruby