Java中如何实现线程(来自C#背景)

4
我正在尝试在我的Java GUI应用程序中实现多线程,以便在运行一些密集方法时释放界面。我主要来自C#开发背景,并在该环境中使用过线程几次,没有遇到太多困难。
大致而言:
C#
创建一个Thread对象 分配一个要启动的方法 启动线程
现在回到Java应用程序本身,它是一个GUI应用程序,有几个按钮执行不同的操作,应用程序使用MIDI API播放MIDI音符,我有play、stop和adding individual notes等功能。(需要注意的关键是,我不播放MIDI文件,而是手动创建音符/消息,通过轨道播放它们)。
有三个特定的操作,我想在它们自己的线程中运行:
1.播放存储的MIDI音符 2.通过文本框显示乐器列表 3.生成100个随机音符
我有一个名为MIDIControl的类,其中包含所有必要的功能,例如实际的操作,以播放、停止和生成所需的消息。在FooView.Java类中为GUI表单本身创建了此对象的实例,这意味着例如:
按“Generate” 事件处理程序在FooView.Java类中执行“GenerateNotes”方法 然后,此方法在MIDIControl实例中执行“Generate”方法
我已经查看了通过Java实现线程的方法,从我所见,它是以不同的方式完成的,有人能解释一下我如何在我的情况下实现线程吗?
如果需要,我可以提供代码示例,感谢您的时间。
5个回答

6

Java线程的创建方式与C#线程相同,只是你需要传递一个Runnable实现而不是委托。(因为Java不支持委托)


我理解Runnable是一个接口,因此每个类只能有一个.run()的实现,或者我错了吗? - Jamie Keeling
1
@Jamie:正确。匿名内部类将有所帮助。http://www.java2s.com/Code/Java/Threads/Creatingthreadswithinnerclasses.htm - SLaks
啊,原来是这样。我从未意识到Java不支持委托以及如何拥有多个.run()实例。感谢您提供的信息! - Jamie Keeling

3

Java并发编程实战是您的指南。请同时查看SwingWorker。请记住,所有与UI相关的更改(无论是组件模型还是其属性)都应始终在事件分派线程上完成。


2

2
您需要区分更新GUI的任务和不更新GUI的任务。
如果您的任务需要更新GUI元素,例如任务(2),则需要子类化SwingWorker。处理代码(对现有库的调用)放在您覆盖的doInBackground()中,通过publish()发送任何数据。然后,您的SwingWorker process()重写可以与Swing组件交互。
原因:Swing不是线程安全的,因此如果从除事件分派线程(EDT)以外的线程访问它,可能会出现问题。process()将在EDT中运行。
对于不更新GUI的任务,请创建一个实现Runnable的新类,并将适当的MIDI库代码调用插入到run()方法中。然后,您可以将其作为目标传递给新线程,如new Thread(myRunnable).start()

1

正如其他人所说,你需要使用 SwingWorker 类。这将使一个 Swing 组件在另一个线程中启动任务,并以线程安全的方式通知其完成和进度。你不能仅仅使用原始线程可运行对象随意创建线程,然后期望通过这些线程与 Swing 交互;Swing 不是线程安全的设计,因此通过这种方式做事情几乎肯定会在代码中引入微妙的线程错误。

根据你使用的 Java 版本,你可以单独下载 SwingWorker 或使用内置于 API 中的版本。

如果你使用的是 Java 6(或更高版本),则 swing worker 在核心 API 这里 中。

如果你使用的是 Java 5,则已经将 Java 6 版本移植到了 这里

如果你使用的是早期版本,则必须添加 sun 的原始版本,即 这里


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接