当我打断它时,为什么我的线程没有结束?

时间:2016-08-13 21:45:12

标签: java multithreading

我正在制作类似skype的程序。我有一个“接受”线程和每个调用的多个用户线程。每次调用开始时,我都会将接受线程存储在arraylist中。我需要做的是当调用中少于两个人中断与发送命令的用户线程一起使用的接受线程时。要在创建接受线程时执行此操作,请记录索引号并将其传递给所有用户线程,因此当需要发送中断命令时,它只使用索引号从arraylist获取线程。但是当我发送它时没有任何反应。有人能告诉我为什么会这样吗?提前谢谢!!!

接受主题

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class accept extends Thread { // Chat and Voice Server User Accept
    private ServerSocket TextChat;
    private Socket sText;
    private int TextPort;
    private int index;
    boolean running = true;

    accept(int ChatPort) {
        TextPort = ChatPort;
        chat.threads.add(this);
        index = chat.threads.indexOf(Thread.currentThread());
        try {
            TextChat = new ServerSocket(ChatPort);
        } catch (IOException e) {
            System.out.println("Cant create server on port "+ ChatPort);
            try {
                TextChat.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
    }
    public void run() {
        while(running == true) {
            try {
                sText = TextChat.accept();
                System.out.println(sText+" Joined the chat");
                new TextChat(sText, TextPort, index).start();
            } catch (IOException e) {
                System.out.println("Server on port "+TextChat+" Can't Accept");
                try {
                    TextChat.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
        System.out.println("Server on port "+TextChat+" Is Shutting Down");
        try {
            TextChat.close();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
    }
    public void setRunning(boolean run) {
        running = run;
    }
}

用户线程

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;

public class TextChat extends Thread {
    private ObjectOutputStream out;
    private ObjectInputStream in;
    private Socket s;
    private String msg;
    private Boolean running = true;
    private int port;
    private String name;
private int threadIndex;

TextChat(Socket sText, int TextPort, int index) {
    s = sText;
    port = TextPort;
    threadIndex = index;
    try {
        out = new ObjectOutputStream(s.getOutputStream());
        if(port <= 65511) {
            chat.users1.add(out);
        }else {
            chat.users2.add(out);
        }
        in = new ObjectInputStream(s.getInputStream());
    } catch (IOException e) {
        e.printStackTrace();
    }
}
public void run() {
    while(running == true) {
        try {
            msg = in.readObject().toString();
            String[] part = msg.split("/");
                if(part[0].equals("MYNAME")) {
                    name = part[1];
                    System.out.println("NAME ADDED "+name);
                }
                if(!msg.equals(null)) {
                    if(port <= 65511) {
                        for(ObjectOutputStream o : chat.users1) {
                            o.writeObject(name+": "+msg);
                        }
                    }else {
                        for(ObjectOutputStream o : chat.users2) {
                            o.writeObject(name+": "+msg);
                        }
                    }
                }
            } catch (ClassNotFoundException | IOException e) {
                System.out.println(name+" Disconneted from chat");
                if(port <= 65511) {
                    chat.users1.remove(out);
                }else {
                    chat.users2.remove(out);
                }
                if(chat.users1.size() < 2) {
                    System.out.println("Chat server on port "+port+" is shutting down due to not enough people in call");
                    chat.threads.get(threadIndex).running = false;
                    running = false;
                }
            }
        }
    }
}

1 个答案:

答案 0 :(得分:2)

当你打断一个线程时,它所做的就是设置一个标志。某些操作会监视此标志,但除非您使用其中一个操作,否则不会发生任何操作。

如果你有一个在IO上被阻塞的线程,解锁线程的最有效的方法是关闭()流或套接字来杀死它。我也会设置一个标志,例如boolean closed因此您可以检测到抛出的任何IOException都是关闭套接字的原因,而不是错误。

编辑:一些建议。

  • 始终使用TitleCase作为类名。
  • 尽可能避免使用可变static字段。在这种情况下,我不相信你需要任何。
  • 始终传递共享状态,并确保从多个线程使用它的线程安全。
  • 不要延长Thread而是实施Runnable并用Thread
  • 包裹它
  • 在这种情况下,您只需要一个服务器端口,除非您将其作为点对点服务实现,但似乎并非如此。
  • while (running == true)执行时,无需编写while (running)等详细表达。
  • 如果您有一个在线程之间共享的boolean running,请确保它是易失性的。
  • DON&#39; T遇到异常并假装它没有发生。你最好在构造函数上throws IOException而不是创建一个死对象。
  • 将每个客户端包装在一个对象中,并且只注册该对象,而不是注册运行该对象的线程。正如您所指出的那样,持有线程并不是非常有用。
  • 当您不期望Boolean值时,请不要使用null之类的包装。使用boolean而不是null
  • 我建议默认使用false的标记。而不是running使用closed。这使得更容易知道变量的默认/正常值是什么。
  • 在代码中没有像这样硬编码端口,你应该传递一个标记或一个id来说明它应该如何表现。
  • 仅使用Object Stream传递常规对象。对于传递文本,您可以使用更简单的Writer / Reader或数据流。
  • 您不需要检查null的值是否为null,例如msg.equals(null)true每次都可以返回Disconneted
  • 使用IDE Disconnected中的拼写检查工具p
  • 如果有人可能即将加入,我就不会断开连接。