如何在Java中终止正在等待阻塞函数调用的线程?

15

我有一个线程:

Thread t = new Thread(){
    public void run(){
        ServerSocketConnection scn = (ServerSocketConnection)
                Connector.open("socket://:1234");
        // Wait for a connection.
        SocketConnection sc = (SocketConnection) scn.acceptAndOpen();
       //do other operation
    }
};
t.start();

假设没有客户端连接到服务器,因此此线程将被阻塞。现在我想要杀死上述线程?我该如何杀死它?

7个回答

11

Thread.interrupt()方法不会中断被阻塞在套接字上的线程。你可以尝试调用Thread.stop()Thread.destroy(),但这些方法已被弃用(编辑:实际上,在J2ME中不存在),并且在某些情况下不起作用,原因可以在此处了解到。

在某些情况下,您可以使用特定于应用程序的技巧。例如,如果一个线程正在等待已知的套接字,则可以关闭该套接字以立即使线程返回。不幸的是,并没有任何通用的技术可行。需要注意的是,在所有等待线程不响应Thread.interrupt()的情况下,它也不会响应Thread.stop()。这些情况包括恶意的拒绝服务攻击和I/O操作,其中Thread.stop()Thread.interrupt()无法正常工作。


你确定吗?你在找哪个API?我在CLDC或MIDP中找不到Thread.stop()... - aioobe
@aioobe:J2SE...无论如何,我要说的是不要使用stop()。 - Tom Crockett
1
我认为主要观点仍然相关:你必须杀死你正在阻塞的内容,不能直接杀死线程... 我猜测 stop() 在 J2ME 中不存在的原因是因为我链接的文章中给出的原因。 - Tom Crockett

0

我刚来到这个页面寻找同样的答案。我找到了一种关闭线程的方法,以下是我用来结束服务器的步骤:

private Thread serverThread;

public void setUp(){
    //Run the server
    serverThread = new Thread() {
        public void run() {
            try {
                new Server(); //it calls acceptAndOpen() here
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    };
    serverThread.start();
}

public void tearDown() {
    serverThread = null;
    System.gc();
}

基本上,将对服务器线程的引用设置为null,然后让垃圾回收器清理资源(即服务器)。
但请注意:这远非完美,我们不应该依赖垃圾回收器来完成其工作,但在我尝试过的每一次中,它似乎都有效。

0
在主线程中(当您想要终止接受线程时),调用scn.close()。然后,acceptAndOpen应该抛出一个IOException异常,您可以捕获并优雅地终止接受线程。
ServerSocketConnection scn =
    (ServerSocketConnection) Connector.open("socket://:1234");

Thread t = new Thread(){
    public void run(){
        // Wait for a connection.
        try {
            SocketConnection sc = (SocketConnection) scn.acceptAndOpen();
            //do other operation
        } catch (IOException e) {
            // Log the exception
        }
    }
};

t.start();

// ...

// Somewhere else...
// Cancel the acceptAndOpen.
scn.close();

一个好的想法是引入一个同步机制,这样你就不会在acceptAndOpen完成后立即关闭套接字。

0

我认为你只需要关闭连接-因此只需将scn作为线程的字段并实现:

public void stop() {
  scn.close();
}

并编写您的主方法以在IOException或其他指示表明您已完成时优雅地退出。


0
你可以调用 thread.interrupt()。这会在你的线程中抛出一个 InterruptedException 异常。

你确定吗?acceptAndOpen未声明抛出InterruptedException。 - aioobe
这是一个运行时异常,不是由acceptAndOpen生成的,而是由Thread类生成的。 - Nikolaus Gradwohl
2
InterruptedException是运行时异常的哪个API?你有URL吗? - aioobe

0

0

将主线程监视线程(从该线程生成新线程的位置)join()到此线程。如果在给定的超时时间后,此线程未“加入”,则可以忽略(nullify)此线程。这将为您添加一个阻塞线程的超时功能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接