当前位置: 首页 > 面试题库 >

Python中的可中断线程连接

郎思远
2023-03-14
问题内容

有什么方法可以等待线程终止,但仍然拦截信号吗?

考虑以下 C 程序:

#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>

void* server_thread(void* dummy) {
    sleep(10);
    printf("Served\n");
    return NULL;
}

void* kill_thread(void* dummy) {
    sleep(1); // Let the main thread join
    printf("Killing\n");
    kill(getpid(), SIGUSR1);
    return NULL;
}

void handler(int signum) {
    printf("Handling %d\n", signum);
    exit(42);
}

int main() {
    pthread_t servth;
    pthread_t killth;

    signal(SIGUSR1, handler);

    pthread_create(&servth, NULL, server_thread, NULL);
    pthread_create(&killth, NULL, kill_thread, NULL);

    pthread_join(servth, NULL);

    printf("Main thread finished\n");
    return 0;
}

一秒钟后结束并打印:

Killing
Handling 10

相反,这是我尝试用 Python 编写的尝试:

#!/usr/bin/env python
import signal, time, threading, os, sys

def handler(signum, frame):
    print("Handling " + str(signum) + ", frame:" + str(frame))
    exit(42)
signal.signal(signal.SIGUSR1, handler)

def server_thread():
    time.sleep(10)
    print("Served")
servth = threading.Thread(target=server_thread)
servth.start()

def kill_thread():
    time.sleep(1) # Let the main thread join
    print("Killing")
    os.kill(os.getpid(), signal.SIGUSR1)
killth = threading.Thread(target=kill_thread)
killth.start()

servth.join()

print("Main thread finished")

它打印:

Killing
Served
Handling 10, frame:<frame object at 0x12649c0>

如何使其表现像C版本?


问题答案:

Jarret Hardie已经提到过:根据Guido van
Rossum的
说法,到目前为止,还没有更好的方法:如文档中所述,join(None)块(这意味着没有信号)。另一种选择-
超时(join(2**31)大约)时进行调用并进行检查isAlive看起来很棒。但是,Python处理计时器的方式是灾难性的,运行python测试程序时使用servth.join(100)而不是可以看到servth.join()

select(0, NULL, NULL, NULL, {0, 1000})  = 0 (Timeout)
select(0, NULL, NULL, NULL, {0, 2000})  = 0 (Timeout)
select(0, NULL, NULL, NULL, {0, 4000})  = 0 (Timeout)
select(0, NULL, NULL, NULL, {0, 8000})  = 0 (Timeout)
select(0, NULL, NULL, NULL, {0, 16000}) = 0 (Timeout)
select(0, NULL, NULL, NULL, {0, 32000}) = 0 (Timeout)
select(0, NULL, NULL, NULL, {0, 50000}) = 0 (Timeout)
select(0, NULL, NULL, NULL, {0, 50000}) = 0 (Timeout)
select(0, NULL, NULL, NULL, {0, 50000}) = 0 (Timeout)
--- Skipped 15 equal lines ---
select(0, NULL, NULL, NULL, {0, 50000}Killing

即,Python每50毫秒唤醒一次,从而导致一个应用程序保持CPU休眠。



 类似资料:
  • 问题内容: 我正在构建一个同时侦听TCP和UDP的应用程序,并且我的关机机制遇到了一些麻烦。当我在每个侦听线程上调用时,TCP线程会因侦听而中断,而UDP侦听器则不会。具体来说,TCP线程使用,它只是返回(没有实际连接)。UDP线程使用,而不会退出该方法。 这是我的JRE,操作系统中的问题,还是我应该切换到? 更新:我已经找到问题的分析。它确认行为不一致。 问题答案: 中断网络IO的常见习惯是关闭

  • 很多情况下,使用信号来终止一个长时间运行的线程是合理的。这种线程的存在,可能是因为工作线程所在的线程池被销毁,或是用户显式的取消了这个任务,亦或其他各种原因。不管是什么原因,原理都一样:需要使用信号来让未结束线程停止运行。这里需要一种合适的方式让线程主动的停下来,而非让线程戛然而止。 你可能会给每种情况制定一个独立的机制,这样做的意义不大。不仅因为用统一的机制会更容易在之后的场景中实现,而且写出来

  • 如果这个线程在对象类的wait()、wait(long)或wait(long,int)方法的调用中被阻塞,或者在该类的thread.join()、thread.join(long)、thread.join(long,int)、thread.sleep(long)或thread.sleep(long,int)方法的调用中被阻塞,那么它的中断状态将被清除,并且它将收到一个interruptedexce

  • 问题内容: 使用return by时,如何中断它? 问题答案: 为此,您需要将任务分配给,而不是调用。当您执行此操作时,将返回一个可用于操纵计划任务的a。特别是,您可以调用关联程序来中断当前正在执行的任务(或者,如果该任务尚未开始运行,则完全跳过执行)。 顺便说一句,由返回的对象实际上是个。

  • 我正在编写一个有3个线程的程序。一个读取一个文本文件并将单词输入到大小为2的ArraylistBlockingQueue中。下一个获取该列表并反转其中的每个其他单词。最后一个线程获取单词并将它们写入一个新的文本文件。 我所有的东西都在工作,除了我不知道如何中断和停止我的线程。程序写入文本文件,但从未结束。 主要方法 输入 反向类@重写公共void run(){ 输出代码@覆盖公共无效run(){