为什么我的线程没有醒来? (JAVA) [英] Why does my thread not wake up? (Java)

查看:148
本文介绍了为什么我的线程没有醒来? (JAVA)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在松散地关注关于Java NIO的教程来创建我的第一个多线程,网络Java应用程序。本教程基本上是关于创建一个echo-server和一个客户端,但目前我只是想让服务器接收来自客户端的消息并将它们记录到控制台。通过在教程页面搜索EchoServer,您可以看到我基于相关代码的类。

I'm loosely following a tutorial on Java NIO to create my first multi-threading, networking Java application. The tutorial is basically about creating an echo-server and a client, but at the moment I'm just trying to get as far as a server receiving messages from the clients and logging them to the console. By searching the tutorial page for "EchoServer" you can see the class that I base most of the relevant code on.

我的问题是(至少我认为是)我无法找到一种方法来初始化要处理的消息队列,以便可以按我的意愿使用它。

My problem is (at least I think it is) that I can't find a way to initialize the queue of messages to be processed so that it can be used as I want to.

应用程序在两个线程上运行:服务器线程,用于侦听连接和套接字数据;以及工作线程,用于处理服务器线程接收的数据。当服务器线程收到消息时,它会在worker上调用 processData(byte [] data),并将数据添加到队列中:

The application is running on two threads: a server thread, which listens for connections and socket data, and a worker thread which processes data received by the server thread. When the server thread has received a message, it calls processData(byte[] data) on the worker, where the data is added to a queue:

1.  public void processData(byte[] data) {
2.      synchronized(queue) {
3.          queue.add(new String(data));
4.          queue.notify();
5.      }
6.  }

在工作线程的<$ c中$ c> run()方法,我有以下代码:

In the worker thread's run() method, I have the following code:

7.  while (true) {
8.      String msg;
9.
10.     synchronized (queue) {
11.         while (queue.isEmpty()) {
12.             try {
13.                  queue.wait();
14.             } catch (InterruptedException e) { }
15.         }
16.         msg = queue.poll();
17.     }
18.
19.     System.out.println("Processed message: " + msg);
20. }

我在调试器中验证了工作线程到达第13行,但是当服务器启动时,不会进入第16行。我认为这是成功等待的标志。我还验证了服务器线程到达第4行,并在队列上调用 notify()。但是,工作线程似乎没有醒来

I have verified in the debugger that the worker thread gets to line 13, but doesn't proceed to line 16, when the server starts. I take that as a sign of a successful wait. I have also verified that the server thread gets to line 4, and calls notify()on the queue. However, the worker thread doesn't seem to wake up.

的javadoc中等待(),声明


当前线程必须拥有此对象的监视器。

The current thread must own this object's monitor.

鉴于我对线程的经验不足,我不确定这意味着什么,但我尝试从工作线程中实例化队列但没有成功。

Given my inexperience with threads I am not exactly certain what that means, but I have tried instantiating the queue from the worker thread with no success.

为什么我的线程没有醒来?如何正确唤醒它?

Why does my thread not wake up? How do I wake it up correctly?

正如@Fly建议的那样,我添加了一些日志调用来打印 System.identityHashCode(队列)并确定队列是不同的实例。

As @Fly suggested, I added some log calls to print out System.identityHashCode(queue) and sure enough the queues were different instances.

这是整个工人类:

public class Worker implements Runnable {
    Queue<String> queue = new LinkedList<String>();
    public void processData(byte[] data) { ... }
    @Override
    public void run() { ... }
}

该工作程序在 main 方法中实例化,并按如下方式传递给服务器:

The worker is instantiated in the main method and passed to the server as follows:

public static void main(String[] args)
{
    Worker w = new Worker();
    // Give names to threads for debugging purposes
    new Thread(w,"WorkerThread").start();
    new Thread(new Server(w), "ServerThread").start();
}

服务器保存工人实例到私有字段并在该字段上调用 processData()。为什么我没有获得相同的队列?

The server saves the Worker instance to a private field and calls processData() on that field. Why do I not get the same queue?

现在可以使用此处获取服务器和工作线程的完整代码。

The entire code for the server and worker threads is now available here.

我已将两个文件中的代码放在同一个粘贴中,因此如果您想自己编译并运行代码,则必须再次将它们拆分。此外,还有对 Log.d() Log.i() Log.w()和 Log.e() - 这些只是简单的日志记录例程,用于构造带有一些额外信息的日志消息(时间戳)和输出到 System.out System.err

I've placed the code from both files in the same paste, so if you want to compile and run the code yourself, you'll have to split them up again. Also, there's abunch of calls to Log.d(), Log.i(), Log.w() and Log.e() - those are just simple logging routines that construct a log message with some extra information (timestamp and such) and outputs to System.out and System.err.

推荐答案

我猜你会得到两个不同的队列对象,因为你正在创建一个全新的 Worker 个实例。您没有发布启动 Worker 的代码,但假设它还实例化并启动 Server ,那么问题在于您分配 this.worker = new Worker(); 而不是将其分配给 Worker 参数。

I'm going to guess that you are getting two different queue objects, because you are creating a whole new Worker instances. You didn't post the code that starts the Worker, but assuming that it also instantiates and starts the Server, then the problem is on the line where you assign this.worker = new Worker(); instead of assigning it to the Worker parameter.

    public Server(Worker worker) {
            this.clients = new ArrayList<ClientHandle>();
            this.worker = new Worker(); // <------THIS SHOULD BE this.worker = worker;
            try {
                    this.start();
            } catch (IOException e) {
                    Log.e("An error occurred when trying to start the server.", e,
                                    this.getClass());
            }
    }

工人的线程可能正在使用 worker 实例传递给Server构造函数,因此Server需要将自己的worker引用分配给同一个Worker对象。

The thread for the Worker is probably using the worker instance passed to the Server constructor, so the Server needs to assign its own worker reference to that same Worker object.

这篇关于为什么我的线程没有醒来? (JAVA)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆