如何在 Java 中关闭线程?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2299522/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 20:30:17  来源:igfitidea点击:

How to close a thread in Java?

javamultithreadingsockets

提问by Alex

I'm very new to Java, and I'm trying to modify an example of a socket server to power a flash-based game. To allow flash to connect to the server, I need to serve up a policy file.

我对 Java 非常陌生,我正在尝试修改套接字服务器的示例以支持基于 Flash 的游戏。为了让闪存连接到服务器,我需要提供一个策略文件。

I've never coded a server application before, so I'm not too familiar with the things which need to happen.

我以前从未编写过服务器应用程序,所以我不太熟悉需要发生的事情。

Anyway, I have made it so that it outputs the file, but for some reason it does so 10 times.

无论如何,我已经做到了,它可以输出文件,但由于某种原因,它输出了 10 次。

I need to close the thread before it continues to do it again. Below is the code I have, with a comment where I need to close the thread.

我需要关闭线程,然后才能继续执行此操作。下面是我的代码,在我需要关闭线程的地方有一个注释。

import java.io.*;
import java.net.*;
import java.util.Random;

public class Main {

  private static int port=4041, maxConnections=0;
  // Listen for incoming connections and handle them
  public static void main(String[] args) {
    int i=0;

    try{
      ServerSocket listener = new ServerSocket(port);
      Socket server;

      while((i++ < maxConnections) || (maxConnections == 0)){
        doComms connection;

        server = listener.accept();
        doComms conn_c= new doComms(server);
        Thread t = new Thread(conn_c);
        t.start();
      }
    } catch (IOException ioe) {
      System.out.println("IOException on socket listen: " + ioe);
      ioe.printStackTrace();
    }
  }

}

class doComms implements Runnable {
    private Socket server;
    private String line,input;

    doComms(Socket server) {
      this.server=server;
    }

    public void run () {

        char EOF = (char)0x00;
      input="";

      try {
        // Get input from the client
        DataInputStream in = new DataInputStream (server.getInputStream());
        PrintStream out = new PrintStream(server.getOutputStream());

        while((line = in.readLine()) != null && !line.equals(".")) {
          input=input + line;
          if(line.trim().equals("h")){

              out.println("h"+EOF);

          }
          else if(line.trim().equals("i")){

               Random randomGenerator = new Random();
               int randomInt = randomGenerator.nextInt(4);

              out.println("b"+randomInt+EOF);


          }
          else if(line.trim().equals("c")){ System.out.println("Player collision.");}
          else if (line.trim().equals("<policy-file-request/>")) {
            out.println("<?xml version=\"1.0\"?>\n<!DOCTYPE cross-domain-policy SYSTEM \"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd\"><cross-domain-policy>\n<site-control permitted-cross-domain-policies=\"all\"/>\n<allow-access-from domain=\"*\"/>\n</cross-domain-policy>"+EOF);
            System.out.println("Responded to policy request");
            // I need to close the thread / disconnect the client here.
          }
          else System.out.println("Unknown command: "+line.trim());

        }
        server.close();
      } catch (IOException ioe) {
        System.out.println("IOException on socket listen: " + ioe);
        ioe.printStackTrace();
      }
    }
}

Also, a small extra thing, in NetBeans, it underlines "import java.io.*;" and says incorrect package, but it still works fine.

另外,在 NetBeans 中,还有一个额外的小东西,它强调“import java.io.*;” 并说不正确的包,但它仍然可以正常工作。

Edit:I've worked out that the reason it sends it 10 times is that it is receiving 10 lines in a single send operation. I have tried adding a "return;" under where it sends the policy XML, but it still doesn't seem to d/c the client. I should also note than I am intending for this to be a multiplayer server, so I need to keep the socket open and just close one thread.

编辑:我发现它发送 10 次的原因是它在一次发送操作中接收了 10 行。我试过添加一个“返回;” 在它发送策略 XML 的地方,但它似乎仍然没有通知客户端。我还应该注意,我打算将其用作多人服务器,因此我需要保持套接字打开并关闭一个线程。

回答by Péter T?r?k

At first glance, your run()method looks like it should terminate normally. I suspect your loop:

乍一看,您的run()方法看起来应该正常终止。我怀疑你的循环:

while((i++ < maxConnections) || (maxConnections == 0)){

Since maxConnectionsis initialized to 0 and is never incremented, the loop seems to run infinitely and create many threads - probably as many as the socket can accept listeners. And then it breaks out from the loop with an IOException. Is this what's actually happening?

由于maxConnections初始化为 0 并且从不递增,循环似乎无限运行并创建许多线程 - 可能与套接字可以接受的侦听器一样多。然后它从循环中以IOException. 这是实际发生的事情吗?

Update:apparently not... out of ideas for now.

更新:显然不是......暂时没有想法。

回答by abc

Your code makes sense. What is your input? If you have 10 lines saying "<policy-file-request/>" , then indeed it will print the file 10 times. What about all the other if clauses you have there? In each one you print something + EOF, but surely you just want to print one response per request. Also your 'input' variable is unused.

你的代码是有道理的。你的输入是什么?如果你有 10 行说 "<policy-file-request/>" ,那么它确实会打印文件 10 次。你那里的所有其他 if 子句呢?在每一个中你打印一些东西 + EOF,但你肯定只想打印每个请求的一个响应。您的“输入”变量也未使用。

回答by Harold L

The thread will die after you return from doComms.run(). Please capitalize the start of class names in Java: it should be DoComms, just to make the code easier to follow for other Java programmers.

从 doComms.run() 返回后,该线程将死亡。请在 Java 中将类名的开头大写:它应该是 DoComms,只是为了让其他 Java 程序员更容易理解代码。

To close the connection, your call to server.close()should do it. To make sure the output is sent fully first, you should call close()or flush()on your PrintStreambefore you call Socket.close().

要关闭连接,您server.close()应该调用它。为确保首先完全发送输出,您应该在调用之前调用close()flush()on your 。PrintStreamSocket.close()

What input are you sending? It looks like if you only send <policy-file-request/>once from the client, you'll only get the file once.

你发送什么输入?看起来如果你只<policy-file-request/>从客户端发送一次,你只会得到一次文件。

Not sure about NetBeans, but is it complaining that you don't have a packagespecified at the top of your .javafile? Try adding the following package declaration, with the path relative to the top of the NetBeans project:

不确定 NetBeans,但它是否在抱怨package您的.java文件顶部没有指定?尝试使用相对于 NetBeans 项目顶部的路径添加以下包声明:

package my.path.to.this.directory;

回答by rob

I'd suggest running both the server and the client in a debugger and stepping through the execution to see what happens at each point in time. This will help you confirm the expected values at every point. Eclipse and other Java IDEs have pretty good (and easy-to-use) debuggers.

我建议在调试器中同时运行服务器和客户端,并逐步执行以查看每个时间点发生的情况。这将帮助您确认每个点的预期值。Eclipse 和其他 Java IDE 具有非常出色(且易于使用)的调试器。

As far as your code:

至于你的代码:

  1. I would do line.trim() once for each loop iteration, instead of trim()'ing repeatedly and unnecessarily creating extra objects.
  2. Make sure the client and server both flush() the Socket's OutputStream after each request/response. If the socket's OutputStream has not been flushed, the InputStream on the other end of the connection may block waiting for input, while the OutputStream blocks waiting to fill its buffer.
  3. What does the code in the client look like? Are you sure it's sending a null or "." to close the connection? Do you need to trim() before checking for a "."
  4. As others have mentioned, your code does not follow typical Java coding conventions. I'd suggest getting up to speed by reading the published code conventions for Java.
  1. 我会为每个循环迭代执行 line.trim() 一次,而不是重复和不必要地创建额外的对象。
  2. 确保客户端和服务器在每次请求/响应后都刷新()套接字的输出流。如果套接字的 OutputStream 尚未刷新,则连接另一端的 InputStream 可能会阻塞等待输入,而 OutputStream 阻塞等待填充其缓冲区。
  3. 客户端中的代码是什么样的?你确定它正在发送一个空值或“。” 关闭连接?在检查“。”之前是否需要修剪()?
  4. 正如其他人所提到的,您的代码不遵循典型的 Java 编码约定。我建议通过阅读已发布的 Java 代码约定来加快速度。