线程在notifyall()之后没有返回

2023-12-06

我是 Java 多线程的新手。我做了一些研究,阅读了教程,并做了测试,但我仍然遇到这个问题。基本上,我正在设置游戏的骨架,我想要主活动类,一个包含方法的线程类,执行缓慢的操作(读取文件并将内容解压到缓冲区),并有一个线程是游戏循环对 UI 操作的反应。

首先,我有一个主活动类,它实例化并启动一个单独的线程:

public class ExperimentsActivity extends Activity {

// This is just a container class with some member data such as ByteBuffers and arrays
TestClass tclass = new TestClass(this);

// Main looping thread
MainLoopThread loop;
Thread mainLoop;

// Start the main looping thread which will trigger the engine's operations
loop = new MainLoopThread(tclass);
mainLoop = new Thread(loop);
mainLoop.start();
loop.setRunning(true);

(...)
}

然后,我有MainLoopThread实现游戏逻辑线程的类:

public class MainLoopThread implements Runnable  {

public boolean running;
private TestClass baseData;

// Thread for data loading/unpacking ( CLASS DEFINITION BELOW )
GFXUnpack dataUnpack;
Thread dataUnpackThread;

public MainLoopThread( TestClass testClassStructure ) {
    running = false;
    baseData = testClassStructure;
}

public void setRunning ( boolean run ) {
    if ( run == true )
    {
        // Launch the thread which manages loading and unpacking graphics
        dataUnpack = new GFXUnpack(baseData.filepack[0]);
        dataUnpackThread = new Thread(dataUnpack);
        dataUnpackThread.start();
        dataUnpack.setRunning(true);
        fileOpened = false;

        // Open the GFX packet file
        try {
            synchronized (this) {
                dataUnpack.setOperation(2);                     
                Log.d("MainLoopThread", "File opening : waiting...");
                while ( dataUnpack.fileOpened == false ) {
                    wait();
                }
                Log.d("MainLoopThread", "File opening wait completed");
            }

            if ( dataUnpack.outCode == -1 ) 
                    Log.d("MainLoopThread", "File opening error !!");
                else fileOpened = true;
                    Log.d("MainLoopThread", "File opening completed");
            } 
            catch ( Exception exp ) {
                Log.d("MainLoopThread", "File opening code exception !!" + exp);
            }
        }
        else if ( dataUnpack.running == true ) dataUnpack.setRunning(false);              running = run;
    }

    // ------------------------------------
    // Here is the main looping thread. All the events related to loading 
    // and unpacking graphics go here
    public void run() {
        while (running) {
            synchronized (this) {
              // ------ Read a GFX packet and update texture pixels
              if ( fileOpened == true ) {
                  try {
                      // ( Do some stuff... )
                      wait();
                  } catch ( Exception exp ) {
                  Log.d("MainLoopThread", "Exception thrown !! " + exp );
              }
          }
      } // ( Thread-out code removed. Anyway, it never passed here )
  }         

最后,GFXUnpackthread类,包含打开SD卡上文件的代码, 读取其中的内容并写入缓冲区:

public class GFXUnpack implements Runnable {
// -------------    
public boolean running = false;
private Filedata fdata;
private int operation = 0, parameter = 0;
public boolean fileOpened;
public int outCode;  // Used to signal the caller about the outcome of the operation
// ------------------------------
public GFXUnpack ( Filedata packetDataStructure ) {
    this.fdata = packetDataStructure;
}
// --------
public void setRunning ( boolean run ) {
    running = run;   operation = 0;  fileOpened = false;            
    outCode = 0;      parameter = 0;
}
// --------
public void setOperation ( int op ) {
    operation = op;
}
// ---
public void setOperation ( int op, int parm ) {
    operation = op;
    parameter = parm;
}
// ---------    
public synchronized void run() {
    while (running) {
        try {
      switch ( operation ) {
                case ( 2 ) :  // Open the gfx data file
                        ( ...do stuff... )
                        break;                  
                    }
                    // ---------
                    try {
                           ( ...Do some stuff here... )
                           Log.d("GFXUnpack", "Mapping file");
                           ( ...Do some stuff here... )
                           Log.d("GFXUnpack", "Mapped file");
                           fileOpened = true;
                           outCode = 1;
                    } catch ( Exception e ) {
                        Log.d("GFXUnpack", "File opening exception !! " + e);
                        outCode = -1;
                    }
                    finally {
                        operation = 0;       parameter = 0;
                        notifyAll();
                        Log.d("GFXUnpack", "Notified file opening");
                    }
                }
                break;
    // ----------------
            }
            // ----- Other cases here... 
        } finally {
        }
    }
}

当我运行上面的代码时,调试器输出是:

MainLoop 线程文件打开:等待...
GFXUnpack 映射文件
GFXUnpack 映射文件
GFXUnpack 通知文件打开

然后,应用程序挂起,我必须强制关闭它。我想,自从我打电话以来notifyAll() in the run()的方法GFXunpack(在里面finally{}块),调用者线程(MainLoop 线程)将继续,我会看到调试器消息“文件打开已完成”,但应用程序挂起。

有谁知道为什么会发生这种情况?


The MainLoopThread实例等待this(一个实例MainLoopThread),以及GFXUnpack实例通知this(一个实例GFXUnpack)。因此通知程序不会通知等待线程。

这两个对象必须使用相同的对象实例等待并通知。更好的是,您应该使用来自java.util.concurrent包,如 Semaphores、CountDownLatches 等,而不是这些难以使用的低级方法。

而且,wait()应始终在一个循环中调用,该循环检查是否实现了唤醒所需的条件,如果没有实现,则由于虚假唤醒而再次开始等待。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

线程在notifyall()之后没有返回 的相关文章

随机推荐

  • 在 C# 中生成随机小数

    如何获得随机的 System Decimal System Random不直接支持 编辑 删除旧版本 这与 Daniel 的版本类似 但会给出完整的范围 它还引入了一种新的扩展方法来获取随机的 任何整数 值 我认为这很方便 注意这里小数的分
  • 用于 C++ 的基于行的线程安全 std::cerr

    创建自己的最简单方法是什么std cerr这样它是逐行线程安全的 我最好寻找代码来做到这一点 我需要的是这样a line of output 终止于std endl 由一个线程生成as a line of output当我实际在控制台上看到
  • python3导入语句的变化

    我不明白以下内容pep 0404 在 Python 3 中 包内的隐式相对导入不再 可用 只有绝对导入和显式相对导入 支持的 此外 星号导入 例如 from x import 仅 允许在模块级代码中使用 什么是相对进口 python2中还有
  • C/C++,你可以将文件#include 到字符串中吗? [复制]

    这个问题在这里已经有答案了 我有一个 C 源文件和一个 Python 源文件 我希望 C 源文件能够将 Python 源文件的内容用作大字符串文字 我可以做这样的事情 char python code include script py 但
  • Nestjs:猫鼬中子文档数组的正确模式(没有默认_id或重新定义ObjectId)

    我正在使用 Nest js 并尝试使用包含子文档字段数组的装饰器创建一个架构 我在导入 导出架构并将其转换为模型方面没有任何麻烦 直到 我在我的中收到以下错误service file 经过几个小时的谷歌搜索后 我发现真正的原因是array子
  • 为什么同一文件中的全局符号需要重新定位?

    我有一个用于测试的 C 程序 a c int a 0 static int fa local a 78 int b int c int fa global a 7777 fa local int test a 6666 fa global
  • python程序在sublime text 3中执行失败,但在bash中执行成功[重复]

    这个问题在这里已经有答案了 encoding utf 8 from future import absolute import division print function unicode literals text 我们的世界充满了未知
  • Select MAX(field)+1 FROM ... 并发问题

    您好 我担心合作伙伴应用程序的并发性 因为最近几天它在 CRUDS 操作方面遇到了麻烦 尤其是在插入方面 所以我运行 SQL Profiler 并注意到他的插入语句不使用事务 而且他正在使用 INSERT INTO TABLEA VALUE
  • 节点“req 未定义”

    当我尝试启动以下脚本时 var http require http http createServer function request response response writeHead 200 Content Type text p
  • Groovy 调用运算符在类字段上使用时会抛出 MissingMethodException

    我正在尝试使用呼叫操作员 重载 但它不适用于类字段 怎么了 class Foo void call int x println x x class MyCallable Foo foo new Foo Foo foo new Foo foo
  • 迭代器上的限制是否有效

    我在实际生产代码中发现了以下内容 我怀疑它实际上有未定义的行为 但是 我在 cppreference 上找不到相关信息 您能否确认这是 UB 或有效代码以及为什么这是 UB 有效 最好带有标准引用 include
  • 在 PHP 或 MySQL 中查找两个日期之间的差异

    此查询不返回 1 月份的记录 但返回 2 月份的记录 SELECT EventAsstCharged CustomerName EventID EventName EventExpectedCharges EventActuallyChar
  • 通过 PayPal(一次)支付多件商品

    我有一个产品列表 我想在其中添加 立即付款 按钮 以便我可以允许我的客户通过 Paypal 付款 我已经浏览了文档 但找不到如何执行此操作 我可以添加多个项目 但这并不方便 因为我已经有了要处理的项目列表 我还需要结账流程来逐项列出订单 因
  • 如何处理上溢和下溢?

    我是 Matlab 新手 试图弄清楚当答案实际上在范围内时如何处理溢出和下溢算术 例如 x 2e 160 x x x which returns inf an overflow x sqrt x which is in the range
  • 来自 javascript 对象的 js-ctypes

    我正在开发一个 Firefox 扩展 它接收二进制图像数组缓冲区 of uint8 t 在我的扩展中 我加载了一个 dll 文件 该文件具有我需要在收到的图像上使用的函数 该函数需要一个ctype uint8 t ptr参数并返回一个cty
  • Entity Framework 4 SaveChanges 内存不足

    我有一个包含超过 50 万条记录的表 每条记录包含大约 60 个字段 但我们只对其中三个进行更改 我们根据计算和查找对每个实体进行小修改 显然我无法依次更新每个实体然后SaveChanges因为那会花费太长时间 所以在整个过程结束时我调用S
  • 如何覆盖Titan数据库中的顶点ID?

    我正在使用生成对象的框架Node并且他们已经分配了一个 id 现在它们需要转换为具有框架中控制的相同ID的Titan顶点 通过访问node id public long addNode Node node TitanVertex verte
  • 何时使用抽象类作为类型

    因此 在尝试理解抽象类时 我仍然对一件事感到困惑 你什么时候想要声明其抽象类的对象类型 例如 public abstract class GameObject public abstract void draw public static
  • 根据 Pandas 中的条件添加行

    我有一个 pandas 数据框 如下所示 Index Year Month Fruit Count 0 2021 03 Apple 2 1 2021 03 Orange 3 2 2021 03 Mango 4 3 2021 04 Apple
  • 线程在notifyall()之后没有返回

    我是 Java 多线程的新手 我做了一些研究 阅读了教程 并做了测试 但我仍然遇到这个问题 基本上 我正在设置游戏的骨架 我想要主活动类 一个包含方法的线程类 执行缓慢的操作 读取文件并将内容解压到缓冲区 并有一个线程是游戏循环对 UI 操