Scene:
Frequently, the following problems are encountered: Many IO busy applications take a multi-threaded approach, but at this point the Python command line does not respond to ctrl-c, and the corresponding Java code is no problem:
The code is as follows:
public class Test {
public static void Main (string[] args) throws Exception {
New Thread (New Runnable () {
public void Run () {
Long start = System.currenttimemillis ();
while (true) {
try {
Thread.Sleep (1000);
} catch (Exception e) {
}
System.out.println (System.currenttimemillis ());
if (System.currenttimemillis ()-Start > *) break;
}
}
}). Start ();
}
}
Java Test
CTRL-C will end the program.
and the corresponding Python code:
The code is as follows:
#-*-Coding:utf-8-*-
Import time
Import threading
Start=time.time ()
Def foreverloop ():
Start=time.time ()
While 1:
Time.sleep (1)
Print Time.time ()
If Time.time ()-start>100:
Break
Thread_=threading. Thread (Target=foreverloop)
#thread_. Setdaemon (True)
Thread_.start ()
Python p.py
After the ctrl-c is completely ineffective.
Immature analysis:
First of all, setting the daemon to true is not an explanation. When Daemon is false, after importing the Python line libraries in fact, threading will check if there is a thread that is not daemon after the main thread has finished executing, some wait for the thread to end, and all the signals sent to the main thread will be blocked during the main thread wait. , you can verify this by adding the signal module to the code above:
The code is as follows:
def sigint_handler (signum,frame):
Print "Main-thread exit"
Sys.exit ()
Signal.signal (signal. Sigint,sigint_handler)
Pressing CTRL-C in 100 seconds does not respond, the print "Main-thread exit" appears only when the child thread ends, and the ctrl-c is blocked.
Threading action at the end of the main thread:
The code is as follows:
_shutdown = _mainthread (). _exitfunc
def _exitfunc (self):
Self._thread__stop ()
t = _picksomenondaemonthread ()
If T:
If __debug__:
Self._note ("%s:waiting for other Threads", self)
While T:
T.join ()
t = _picksomenondaemonthread ()
If __debug__:
Self._note ("%s:exiting", self)
Self._thread__delete ()
For all non-daemon threads to join the wait, in which join can self-view source code, and call wait, with the above analysis, the main thread to wait for a lock.
Immature solution:
Only the thread can be set to daemon to allow the main course not to wait, can accept the ctrl-c signal, but can not let the child thread immediately end, then only use the traditional polling method, using sleep intermittently Save the CPU bar:
The code is as follows:
#-*-Coding:utf-8-*-
Import Time,signal,traceback
Import Sys
Import threading
Start=time.time ()
Def foreverloop ():
Start=time.time ()
While 1:
Time.sleep (1)
Print Time.time ()
If Time.time ()-start>5:
Break
Thread_=threading. Thread (Target=foreverloop)
Thread_.setdaemon (True)
Thread_.start ()
#主线程wait住了, we can't accept the signal.
#thread_. Join ()
Def _exitcheckfunc ():
print "OK"
Try
While 1:
Alive=false
If Thread_.isalive ():
Alive=true
If not alive:
Break
Time.sleep (1)
#为了使得统计时间能够运行, to capture keyboardinterrupt:ctrl-c
Except Keyboardinterrupt, E:
Traceback.print_exc ()
Print "Consume time:", Time.time ()-start
Threading._shutdown=_exitcheckfunc
Cons: Polling always wastes a bit of CPU resources, as well as battery.
There is a better solution please ask.
PS1: Process Monitoring solution:
Use another process to accept the signal and kill the task process, the cow
The code is as follows:
#-*-Coding:utf-8-*-
Import Time,signal,traceback,os
Import Sys
Import threading
Start=time.time ()
Def foreverloop ():
Start=time.time ()
While 1:
Time.sleep (1)
Print Time.time ()
If Time.time ()-start>5:
Break
Class Watcher:
"" This class solves the problems with multithreaded
Programs in Python, (1) a signal might be delivered
to any thread (which is just a malfeature) and (2) if
The thread that gets the signal is waiting, the signal
is ignored (which is a bug).
The Watcher is a concurrent process (not thread) that
Waits for a signal and the process that contains the
Threads. See Appendix A of the Little Book of Semaphores.
http://greenteapress.com/semaphores/
I has only tested this on Linux. I would expect it to
Work on the Macintosh and is on Windows.
"""
def __init__ (self):
"" "creates a child thread, which returns. The parent
Thread waits for a keyboardinterrupt and then kills
The child thread.
"""
Self.child = Os.fork ()
If Self.child = = 0:
Return
Else
Self.watch ()
def watch (self):
Try
Os.wait ()
Except Keyboardinterrupt:
# I put the capital B in Keyboardinterrupt so I can
# When the Watcher gets the SIGINT
print ' Keyboardinterrupt '
Self.kill ()
Sys.exit ()
Def Kill (self):
Try
Os.kill (Self.child, signal. SIGKILL)
Except Oserror:pass
Watcher ()
Thread_=threading. Thread (Target=foreverloop)
Thread_.start ()
Note Watch () must be placed before the thread is created, the reason is unknown .... , or it ends immediately.