Java 如何使用“暂停-然后恢复”或其他选项在线程之间同步共享数据
我正在写一个游戏,其中一个线程-游戏线程-永远循环,更新我所有的精灵,渲染它们,然后在再次执行之前睡眠一段时间。我还有一个定制的事件处理程序,用于处理按键等 在大多数情况下,这一切都很好。但是,如果在GameThread渲染时引发事件,我会遇到一个问题。在极少数情况下,处理事件的处理程序可能会同时更改需要渲染的内容,从而影响GameThread渲染的结果 为了避免这种情况,我希望事件处理程序立即暂停游戏线程,处理事件,然后恢复游戏线程Java 如何使用“暂停-然后恢复”或其他选项在线程之间同步共享数据,java,multithreading,resume,suspend,Java,Multithreading,Resume,Suspend,我正在写一个游戏,其中一个线程-游戏线程-永远循环,更新我所有的精灵,渲染它们,然后在再次执行之前睡眠一段时间。我还有一个定制的事件处理程序,用于处理按键等 在大多数情况下,这一切都很好。但是,如果在GameThread渲染时引发事件,我会遇到一个问题。在极少数情况下,处理事件的处理程序可能会同时更改需要渲染的内容,从而影响GameThread渲染的结果 为了避免这种情况,我希望事件处理程序立即暂停游戏线程,处理事件,然后恢复游戏线程 suspend()/resume()方法适合我的需要,但它们
suspend()
/resume()
方法适合我的需要,但它们已被弃用。然而,在我的例子中,由于死锁的可能性很小,不管怎样使用它们是否安全我需要立即暂停,否则用户将注意到事件处理延迟 如果要同步对资源的访问,请使用ReentrantLock: ReentrantLock sync=新的ReentrantLock() 您必须将该锁传递给要访问共享数据的每个runnable 然后,在您访问相关资源的每个地方,您将使用该共享锁对象,并获取并释放锁(即,您的关键部分): 这是java中相当标准的并发编程。请记住,“lock”是一种阻塞方法,因此您可能希望改用“tryLock”,它允许您尝试获取锁,但会返回一个布尔值,说明您是否实际获得了锁:
if (sync.tryLock()) {
try {
//critical section
}
finally {
sync.unlock();
}
}
有一个版本的“tryLock”会等待给定的时间,然后放弃获取锁并返回假值。通常,您会执行一些线程同步:
List<Shape> shapesToRender;
Object lockObject = new Object(); // Note this must be somehow shared between two threads
// Your rendering thread method
public void renderForever() {
while(true) {
for(Shape shape: shapesToRender) {
synchronized(lockObject) {
render(shape);
}
}
}
}
// One of your event handlers
public void handleEvent(Event event) {
synchronized(lockObject) {
// Process event somehow, e.g. change the color of some of the shapes
event.getShape().setColor(Color.RED);
}
}
列表shapesToRender;
对象锁定对象=新对象();//注意,这必须以某种方式在两个线程之间共享
//渲染线程方法
public void renderForever(){
while(true){
用于(形状:shapesToRender){
已同步(锁定对象){
渲染(形状);
}
}
}
}
//您的事件处理程序之一
公共无效handleEvent(事件){
已同步(锁定对象){
//以某种方式处理事件,例如更改某些形状的颜色
event.getShape().setColor(Color.RED);
}
}
在上述情况下:
- 您将渲染一个形状(所有事件处理程序都将等待该形状完成),或者
- 一些事件处理程序将执行某些操作(渲染线程将等待该操作完成)
(严格地说,这不是死锁。死锁是指线程永远无法继续。在这种情况下,如果可以恢复暂停的线程,其他线程也可以继续。)暂停/恢复被弃用的原因是,很难正确暂停/恢复线程,这要由应用程序开发人员来处理。具有共享标志的解决方案是最常用的。你能发布一些示例代码吗?我认为使用flag并仍然有响应应用程序是可能的。我会避免“synchronized”块,尽管这种方法是有效的(请参阅我发布的答案)。原因是“synchronized”块无法控制阻塞。使用ReentrantLock可以完成一些事情
List<Shape> shapesToRender;
Object lockObject = new Object(); // Note this must be somehow shared between two threads
// Your rendering thread method
public void renderForever() {
while(true) {
for(Shape shape: shapesToRender) {
synchronized(lockObject) {
render(shape);
}
}
}
}
// One of your event handlers
public void handleEvent(Event event) {
synchronized(lockObject) {
// Process event somehow, e.g. change the color of some of the shapes
event.getShape().setColor(Color.RED);
}
}