Java - 创建用于通过Internet发送对象的单独线程

时间:2012-05-30 12:11:29

标签: java multithreading sockets event-handling connection

我正在用Java编写Battleships游戏,用于我的学习中的事件驱动编程。该游戏应该是一个网络游戏,我将在一个应用程序中创建客户端和服务器。

这是表示我的应用程序结构的图像: class diagram http://dl.dropbox.com/u/41993645/mvc.jpeg

为了达到目的 - 我想编写将作为单独线程运行的Server类,并负责远程View - Controller通信。因此,Server类将负责:

  • 在无限循环中从套接字读取对象,如果有的话, 将它们放在Controller的BlockingQueue中。
  • 提供类似'sendActionEventToView()'的方法,它允许Controller以另一种方式传递对象 - 从Controller到远程View。

不幸的是,在运行Server线程时,整个应用程序停止响应。如果有人告诉我我做错了什么,我将非常感激。在我看来,这是服务器代码中存在问题的一部分:

/** Main Server method - responsible for reading objects
 *  and putting them in the queue if any arrived */
public void run() {
  GameEvent event;
  while(true) {
    try {
      event = (GameEvent)objectStream.readObject();
      if(event != null) eventQueue.put(event);
    } catch(ClassNotFoundException e) {
      e.printStackTrace();
    } catch(IOException e1) {
      e1.printStackTrace();
    } catch(InterruptedException e2) {
      e2.printStackTrace(); 
    }
  }
}

我认为线程挂起'readingObject()' - 如果流中没有任何对象,我如何强制它给另一个线程提供处理器时间?

其他服务器:https://github.com/mc-suchecki/Battleships/blob/master/controller/Server.java 该应用的其余部分:https://github.com/mc-suchecki/Battleships

非常感谢您,如果有任何不清楚的地方,请发表评论。对不起我的英语。

5 个答案:

答案 0 :(得分:0)

普通的java流是阻止。这意味着您通常希望每个套接字连接使用2个线程(假设是双向通信)。一个线程专门用于每个插件连接的每个流(输入/输出)

答案 1 :(得分:0)

如果你真的使用多个线程,那么当一个线程被阻塞时,其他线程将会运行。没有必要“强制”处理器给其他线程留出时间。

查看代码,您的视图直接调用Controller的run方法,而不是将其提供给另一个运行的线程: https://github.com/mc-suchecki/Battleships/blob/75e6cf69d081c05845f4171bf42ce096ed5247a7/view/View.java#L48会导致Controller's代码在调用createServer的同一个线程中运行。

在您的要点中,您已经将Controller提交到Controller's构造函数中的新主题(https://gist.github.com/2835863#L46)。我假设您可以在视图中删除对“controller.run()”的调用。

答案 2 :(得分:0)

如果你的代码是public void run();使用Thread的start方法启动,readObject只能阻塞该线程。

答案 3 :(得分:0)

确保您的运行方法有一个自己的线程。我怀疑你用一个线程做了很多事情;所有的线程都是一个线程,它们都在套接字上等待。当他们(单数)读取某些内容时,他们只需返回并再次等待套接字。

使用您的IDE确保您拥有所需的所有线程。使用调试器。挂起程序时暂停程序并检查所有线程。确保你至少有两个。 (如果不这样做,那就是问题。)一个线程挂在套接字读取上。检查其他人(如果存在的话)在哪里挂起并修复代码,这样他们就不会。

答案 4 :(得分:0)

我刚刚发现问题 - 它在构造函数中:

/** Server class constructor */
public Server(BlockingQueue<GameEvent> queue) {
  eventQueue = queue;
  try {
    serverSocket = new ServerSocket(Constants.PORT_NUMBER);
    socket = serverSocket.accept();  
    inputStream = socket.getInputStream();  
    objectStream = new ObjectInputStream(inputStream);  
  } catch(IOException e) {
    e.printStackTrace();
  }  
  Thread thread = new Thread(this);
  thread.start();
}

在{/ 1>}创建单独的线程之前,将socket = serverSocket.accept()行挂起了应用程序。我不知道为什么,但我在run()方法中寻找问题,这是错误的。