实现可中断的线程

在《从nginx日志读取URL来做性能测试》(http://san-yun.iteye.com/blog/1679215)这篇文章中我实现了一个python多线程来做性能测试,但存在一个问题,线程不可中断,包括两方面:
1. 用户通过kill命令来中断
2. 程序满足某种条件中断(比如测试量大于1000则退出)

下面是我的实现:

# -*- coding: utf-8 -*-
import re
import urllib2
import json
import threading
import Queue
import os
import time
from time import sleep
from threading import Lock
from signal import signal,SIGTERM,SIGINT,SIGQUIT

class Executor:
def __init__(self,size):
self.queue = Queue.Queue()
self.tasks = []
self.running = True

for i in range(size):
t = Task(self.queue)
t.setDaemon(True)
t.start()
self.tasks.append(t)

self._signal()

def _signal(self):
signal(SIGTERM,self._exit)
signal(SIGINT,self._exit)
signal(SIGQUIT,self._exit)


def _exit(self,a=None,b=None):
print 'clean'
self.cancel()

def cancel(self):
for task in self.tasks:
while not task.cancel():
pass

self.running = False
self.onCancel()

def submit(self,call):
self.queue.put(call)

def join(self):
#self.queue.join() queue.join()会阻塞,所以不用
while self.running and not self.queue.empty():
sleep(0.1)
if self.cancelTrigger():
self.cancel()

def setCancelTrigger(self,cancelTrigger):
self.cancelTrigger = cancelTrigger

def setOnCancel(self,onCancel):
self.onCancel = onCancel


class Task(threading.Thread):

def __init__(self,queue):
threading.Thread.__init__(self)
self.queue = queue
self.running = True
self.canceled = False

def cancel(self):
self.canceled=True
return self.isCanceled()

def isCanceled(self):
return self.running==False

def run(self):
while self.running:
call = self.queue.get()
call.run()
self.queue.task_done()
if self.canceled:
self.running = False


客户端使用:

host = "http://7.s.duitang.com"

thread_count = 10 #并发数
max_count=100 #运行次数

total = 0
fail = 0
avg = 0
lock = Lock()

def cancelTrigger():
return total>=max_count

def onCancel():
print 'total %s'%total
print 'fail %s'%fail
print 'avg %s'%(avg/total)

if __name__ == "__main__":
f = open("napi","r")
executor = Executor(thread_count)
executor.setCancelTrigger(cancelTrigger)
executor.setOnCancel(onCancel)
analysis(f.readlines(),executor)
executor.join()



在实现的时候比较纠结的点:
1. Task如果不是daemon会导致任务永远不会停止,但是如果Task是daemon线程,main线程结束之后daemon就结束了。所以这时需要实现一个join()来阻塞main线程:

def join(self):
#self.queue.join() queue.join()会阻塞,所以不用
while self.running and not self.queue.empty():
sleep(0.1)
if self.cancelTrigger():
self.cancel()


2. 线程应该可cancel的,之前是直接修改while isrunning的变量,但这样会导致task其实还没有完成的停止下来。所以对于task我引入两个变量来实现安全的停止。



def cancel(self):
for task in self.tasks:
while not task.cancel():
pass

self.running = False
self.onCancel()

def cancel(self):
self.canceled=True
return self.isCanceled()

def run(self):
while self.running:
call = self.queue.get()
call.run()
self.queue.task_done()
if self.canceled:
self.running = False


3.对于signal专门写了一片文章记录()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 线程中写死循环会导致线程一直占用 CPU 资源,影响系统的性能和稳定性。如果需要中断线程,可以使用线程中断机制。 在 Java 中,线程中断机制通过调用线程的 interrupt() 方法实现。该方法会设置线程中断标志位,线程在执行过程中可以检查该标志位,如果标志位被设置,线程可以选择退出执行。 下面是一个示例代码: ```java public class MyThread extends Thread { @Override public void run() { while (!Thread.interrupted()) { // 线程执行的代码 } } } public class Main { public static void main(String[] args) throws InterruptedException { MyThread thread = new MyThread(); thread.start(); // 在主线程中等待一段时间后中断线程 Thread.sleep(1000); thread.interrupt(); } } ``` 在上面的代码中,MyThread 类继承自 Thread,重写了 run() 方法,在 run() 方法中使用 while 循环进行线程执行的代码。在 while 循环中使用 Thread.interrupted() 方法检查线程中断标志位,如果标志位被设置,while 循环会退出,线程也会结束执行。 在 Main 类中,创建了 MyThread 对象并启动线程。在主线程中等待一段时间后,调用 thread.interrupt() 方法中断线程的执行。 ### 回答2: 在线程中使用死循环可能会导致线程无法正常退出,因为线程会一直停留在循环中,无法执行循环外的其他代码。但我们可以通过中断线程的方式来解决这个问题。 要中断一个线程,我们可以使用Thread类提供的interrupt()方法。首先,在循环内部通过检查Thread类的interrupted()方法来确定是否发生了中断请求。如果发生了中断请求,我们可以使用break语句来跳出循环。接下来,我们可以使用return语句或者在循环外部进行清理操作,从而使线程正常退出。 以下是一个简单的示例代码: ```java public class MyThread extends Thread { @Override public void run() { while (!Thread.interrupted()) { // 循环体代码 // 检查是否发生中断 if (Thread.interrupted()) { break; } } // 清理操作 } } public class Main { public static void main(String[] args) { MyThread thread = new MyThread(); thread.start(); // 等待一段时间后中断线程 try { Thread.sleep(1000); thread.interrupt(); } catch (InterruptedException e) { e.printStackTrace(); } } } ``` 在这个示例中,我们创建了一个继承自Thread类的自定义线程类MyThread,并在run()方法中进行了死循环。在循环中,我们通过调用Thread.interrupted()方法来检查是否发生了中断请求。如果中断请求发生,我们使用break语句来跳出循环。在main方法中,我们创建了一个MyThread对象并启动它。然后,通过调用Thread.sleep()方法等待一段时间后,调用thread.interrupt()方法来中断线程。 通过这种方式,我们可以在循环内部检查中断请求并优雅地让线程退出循环,从而中断线程的执行。 ### 回答3: 在线程中使用死循环是为了让线程一直执行某个任务,但有时候我们需要中断这个线程,停止它的执行。下面是一种常见的在线程中写死循环后中断线程的方法: 通常,我们会使用一个boolean类型的变量来标识线程是否继续执行循环。在外部想要中断线程时,我们将这个变量设置为false,从而使线程退出循环。 具体步骤如下: 1. 在线程的类中定义一个boolean类型的成员变量,例如isRunning,并初始化为true。 2. 在线程的run方法中使用while循环,并检查isRunning的值是否为true,如果是则继续执行循环。 3. 当外部需要中断线程时,通过调用线程对象的interrupt()方法发送中断信号给线程。 4. 在线程的run方法中的while循环中,检查线程中断状态,可以使用Thread类的静态方法Thread.interrupted()来检查中断状态,如果检查到中断状态为true,则退出循环。 5. 循环结束后,线程终止执行。 示例代码如下: ```java public class MyThread extends Thread { private volatile boolean isRunning = true; @Override public void run() { while (isRunning) { // 执行线程任务的代码 if (Thread.interrupted()) { // 检查线程中断状态 break; } } // 线程结束执行 } public void stopRunning() { isRunning = false; } } ``` 在外部代码中,我们可以通过调用线程对象的stopRunning()方法来中断线程: ```java public class Main { public static void main(String[] args) { MyThread thread = new MyThread(); thread.start(); // 一段时间后中断线程 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } thread.stopRunning(); } } ``` 这样,当调用stopRunning()方法后,线程的isRunning变量将被设置为false,从而让线程退出死循环,实现中断线程的目的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值