python 다중 루틴 사용법 실례 설명
오늘python 다중 루틴을 배우려고 시도했을 때 갑자기 슈퍼의 사용법에 대해 잘 알지 못했기 때문에 먼저 겪은 문제점을 정리했습니다.다음 코드를 작성하려고 시도할 때
class A():
def __init__( self ):
print "A"
class B( A ):
def __init__( self ):
super( B, self ).__init__( )
# A.__init__( self )
print "B"
b = B()
출현:
super( B, self ).__init__()
TypeError: must be type, not classobj
마지막으로 원래python의 신식 클래스의 문제, 즉 A는 반드시 신식 클래스가 되어야 한다는 것을 발견했다.해결 방법은 다음과 같습니다.
(1)
class A( object ):
def __init__( self ):
print "A"
class B( A ):
def __init__( self ):
super( B, self ).__init__( )
# A.__init__( self ) ## , ,
print "B"
b = B()
(2)
__metaclass__=type
class A():
def __init__( self ):
print "A"
class B( A ):
def __init__( self ):
super( B, self ).__init__( )
# A.__init__( self ) ## , ,
print "B"
b = B()
참고: super(B,self)에 있는 경우.init__( )
문장에self, 즉 슈퍼(B,self)를 추가합니다.init__(self) 다음 오류가 발생합니다.
super( B, self ).__init__( self )
TypeError: __init__() takes exactly 1 argument (2 given)
이상은 단지 약간의 본인의 소감 필기일 뿐입니다, 허허.
import threading, time
class myThread( threading.Thread ):
def __init__( self, threadname = "" ):
#threading.Thread.__init__( self, name = threadname )
super( myThread, self ).__init__( name = threadname )
def run( self ):
print "starting====", self.name, time.ctime()
time.sleep( 5 )
print "end====", self.name, time.ctime(),
m = myThread( "m" )
n = myThread( "n" )
m.start()
n.start()
결과 출력:
starting==== m Mon Aug 08 21:55:41 2011
starting==== n Mon Aug 08 21:55:41 2011
만약 프로세스의 주 루틴이 실행되고 하위 루틴이 실행되고 있다면, 모든 하위 루틴이 끝날 때까지 프로세스가 종료되지 않을 것입니다.예를 들면 다음과 같습니다.
import threading, time
class myThread( threading.Thread ):
def __init__( self, threadname = "" ):
#threading.Thread.__init__( self, name = threadname )
super( myThread, self ).__init__( name = threadname )
def run( self ):
print "starting====", self.name, time.ctime()
time.sleep( 5 )
print "end====", self.name, time.ctime(),
m = myThread( "m" )
m.start()
print "main end"
print
결과 출력:
starting==== m Mon Aug 08 22:01:06 2011
main end
end==== m Mon Aug 08 22:01:11 2011
즉 주 프로세스가 끝난 후에 하위 프로세스가 아직 끝나지 않았다는 것이다
주 프로세스가 끝났을 때 하위 프로세스도 끝났으면 setDaemon () 함수를 사용해야 합니다.
예는 다음과 같습니다.
import threading, time
class myThread( threading.Thread ):
def __init__( self, threadname = "" ):
#threading.Thread.__init__( self, name = threadname )
super( myThread, self ).__init__( name = threadname )
def run( self ):
print "starting====", self.name, time.ctime()
time.sleep( 5 )
print "end====", self.name, time.ctime(),
m = myThread( "m" )
m.setDaemon( True )
m.start()
print "main end"
print
출력 결과: starting====main end m Mon Aug 08 22:02:58 2011
하위 프로세스 m이 끝날 때 인쇄해야 할 "end===..."을 출력하지 않았음을 알 수 있습니다.
간단한 스레드 동기화
개 실행 루틴은 항상 데이터를 공유해야 한다. 공유 데이터만 읽는 것이 좋지만 여러 루틴이 공유 데이터를 수정하려면 예측할 수 없는 결과가 나타날 수 있다.
만약 두 라인의 대상 t1과 t2가 모두 수치num=0을 1씩 증가시켜 연산한다면 t1과 t2가 각각num을 10번씩 수정하면num의 최종 결과는 20이어야 한다.그러나 t1이num의 값을 얻었을 때(가령 이때num이 0이라면) 시스템은 t1을'sleeping'상태로 조정하고 이때 t2는'running'상태로 전환한다. 이때 t2가num의 값도 0이다. 그리고 그는num+1의 값1을num에 부여한다.시스템은 또 t2를'sleeping'상태로 전환했고 t1은'running'상태로 전환했다. t1은 이미num값을 0으로 얻었기 때문에 그도num+1의 값을num에게 1로 부여했다.원래는 2차례에 한 번 더 운행했는데, 결과는num가 한 번만 늘었다.이와 같은 상황은 다선정이 동시에 실행될 때 발생할 수 있다.그래서 이런 상황의 발생을 방지하기 위해서는 라인 동기화 메커니즘을 사용해야 한다.
가장 간단한 동기화 메커니즘은 바로 잠금이다
자물쇠 대상은threading을 사용합니다.RLock 클래스 생성
mylock = threading.RLock()
어떻게 자물쇠를 사용하여 라인을 동기화합니까?라인은 자물쇠의 acquire () (획득) 방법을 사용할 수 있으며, 이렇게 하면 자물쇠가'locked '상태로 들어갑니다.매번 한 라인만 자물쇠를 얻을 수 있다.다른 라인이 이 자물쇠를 얻으려고 시도할 때 시스템이'blocked '상태로 바뀌어 자물쇠가 있는 라인이 자물쇠의release () (방출) 방법을 호출할 때까지 자물쇠가'unlocked' 상태로 들어간다.Blocked 상태의 라인은 알림을 받고 자물쇠를 받을 권리가 있습니다.만약 여러 개의 라인이'blocked'상태에 있다면 모든 라인은'blocked'상태를 해제한 다음에 시스템이 한 라인을 선택해서 자물쇠를 얻고 다른 라인은 계속 침묵할 것이다('blocked').
import threading
mylock = threading.RLock()
class mythread(threading.Thread)
...
def run(self ...):
... #
mylock.acquire()
... #
mylock.release()
... #
우리는 공유 데이터를 수정하는 코드를 '임계구' 라고 부른다. 모든 '임계구' 를 같은 자물쇠 대상의 acquire () 와release () 방법 호출 사이에 폐쇄해야 한다.
자물쇠는 가장 기본적인 동기화 단계만 제공할 수 있습니다.어떤 사건이 발생했을 때만 임계 구역에 접근하는 등 더 복잡한 라인 동기화가 필요할 때가 있다. 예를 들어 어떤 수치가 바뀌었을 때.이렇게 하려면 조건 변수를 사용해야 합니다.
조건 변수는threading을 사용합니다.Condition 클래스 생성
mycondition = threading.Condition()
조건 변수는 어떻게 일합니까?첫 번째 라인이 조건 변수를 성공적으로 얻은 후, 이 조건 변수의wait () 방법을 사용하면 이 라인이 이 자물쇠를 풀고'blocked '상태로 들어갑니다. 다른 라인이 같은 조건 변수의 notify () 방법을 사용해서'blocked' 상태로 들어간 라인을 깨울 때까지.이 조건 변수의 notify All () 방법을 호출하면 기다리는 모든 라인을 깨울 것입니다.
프로그램이나 루틴이 영원히'blocked'상태에 있으면 자물쇠가 사라집니다.따라서 자물쇠, 조건 변수 등 동기화 메커니즘을 사용했다면 반드시 꼼꼼하게 검사하여 자물쇠가 사라지는 상황을 방지해야 한다.이상이 발생할 수 있는 임계 구역에는 이상 처리 메커니즘의finally 자구를 사용하여 자물쇠를 방출해야 한다.조건 변수를 기다리는 라인은 notify () 방법으로 깨우쳐야 합니다. 그렇지 않으면 영원히 침묵합니다.모든 wait () 방법이 호출될 때 대응하는 notify () 호출이 있어야 하며, 만일을 대비해서 notify All () 방법을 호출할 수도 있습니다.
동기화 대기열
우리는 항상 생산자/소비자 관계의 두 라인을 이용하여 공유 버퍼의 데이터를 처리한다.예를 들어 하나의 생산자 라인은 사용자 데이터를 공유 버퍼에 넣고 소비자 라인이 데이터를 추출하는 처리를 기다린다.그러나 버퍼링 구역이 너무 작고 생산자와 소비자 두 개의 비동기적인 라인의 속도가 같지 않으면 한 라인이 다른 라인을 기다리는 상황이 발생하기 쉽다.공유 자원을 최대한 단축하고 같은 속도로 작업하는 각 라인의 대기 시간을 줄이기 위해서, 우리는 추가 버퍼를 제공할 수 있는 '대기열' 을 사용할 수 있습니다.
다음 코드를 사용하여 대기열 객체를 만듭니다.
import Queue
myqueue = Queue.Queue(maxsize = 10)
Queue.Queue 클래스는 대기열의 동기화 구현입니다.대기열의 길이는 무한하거나 제한될 수 있습니다.Queue의 구조 함수의 선택할 수 있는 매개 변수 maxsize를 통해 대기열 길이를 설정할 수 있습니다.maxsize가 1보다 작으면 대기열의 길이가 무한하다는 것을 의미합니다.
대기열에 값을 삽입하려면 다음과 같이 하십시오.
myqueue.put(10)
대기열 대상의put () 방법을 호출하여 대기열 끝에 항목을 삽입합니다.put()에는 두 개의 매개 변수가 있는데 첫 번째 item은 필수 항목이고 삽입된 항목의 값이다.두 번째 Block은 선택할 수 있는 매개 변수입니다. 기본값은 1입니다.대기열이 비어 있고 Block이 1이면, put () 방법은 데이터 단원이 비어 있을 때까지 호출 라인을 정지시킵니다.Block이 0이면 put 방법은 Full 이상을 일으킬 수 있습니다.
대기열에서 값을 체크 아웃하려면 다음과 같이 하십시오.
myqueue.get()
대기열 대상의 get () 방법을 호출해서 헤더에서 항목을 삭제하고 되돌려줍니다.선택할 수 있는 매개 변수는 Block이고 기본값은 1입니다.대기열이 비어 있고 Block이 1이면 get () 은 항목이 사용할 수 있을 때까지 호출 라인을 정지합니다.Block이 0이면 대기열에서 Empty 예외가 발생합니다.
Queue를 사용하는 방법을 예로 살펴보겠습니다.
# queue_example.py
from Queue import Queue
import threading
import random
import time
# Producer thread
class Producer( threading.Thread ):
def __init__( self, threadname, queue ):
threading.Thread.__init__( self, name = threadname )
self.sharedata = queue
def run( self ):
for i in range( 20 ):
print self.getName(), 'adding', i, 'to queue'
self.sharedata.put( i )
time.sleep( random.randrange( 10 ) / 10.0 )
print self.getName(), 'Finished'
# Consumer thread
class Consumer( threading.Thread ):
def __init__( self, threadname, queue ):
threading.Thread.__init__( self, name = threadname )
self.sharedata = queue
def run( self ):
for i in range( 20 ):
print self.getName(), 'got a value:', self.sharedata.get()
time.sleep( random.randrange( 10 ) / 10.0 )
print self.getName(), 'Finished'
# Main thread
def main():
queue = Queue()
producer = Producer( 'Producer', queue )
consumer = Consumer( 'Consumer', queue )
print 'Starting threads ...'
producer.start()
consumer.start()
producer.join()
consumer.join()
print 'All threads have terminated.'
if __name__ == '__main__':
main()
프로그램 출력 결과는 다음과 같습니다.
Starting threads ...
Producer adding 0 to queue
Consumer got a value: 0
Producer Finished
Producer adding 1 to queue
Producer Finished
Producer adding 2 to queue
Consumer Finished
Consumer got a value: 1
Consumer Finished
Consumer got a value: 2
Consumer Finished
Consumer got a value: Producer Finished
Producer adding 3 to queue
3
Consumer Finished
Consumer got a value: Producer Finished
Producer adding 4 to queue
4
ConsumerProducer Finished
ConsumerFinished
got a value:Producer adding 5 to queue
5
Consumer Finished
Consumer got a value: Producer Finished
Producer adding 6 to queue
Producer Finished
Producer adding 7 to queue
6
Consumer Finished
Consumer got a value: 7
Producer Finished
Producer adding 8 to queue
Producer Finished
Producer adding 9 to queue
Consumer Finished
Consumer got a value: 8
ConsumerProducer FinishedFinished
ConsumerProducer got a value:adding 109
to queue
Producer Finished
Producer adding 11 to queue
Producer Finished
Producer adding 12 to queue
ConsumerProducer FinishedFinished
ConsumerProducer got a value:adding 1310
to queue
Producer Finished
Producer adding 14 to queue
Consumer Finished
Consumer got a value: 11
Producer Finished
Producer adding 15 to queue
Producer Finished
Producer adding 16 to queue
Producer Finished
Producer adding 17 to queue
Producer Finished
Producer adding 18 to queue
Consumer Finished
Consumer got a value: 12
Producer Finished
Producer adding 19 to queue
Producer Finished
Consumer Finished
Consumer got a value: 13
Consumer Finished
Consumer got a value: 14
Consumer Finished
Consumer got a value: 15
Consumer Finished
Consumer got a value: 16
Consumer Finished
Consumer got a value: 17
Consumer Finished
Consumer got a value: 18
Consumer Finished
Consumer got a value: 19
Consumer Finished
All threads have terminated.
본고에서 서술한 것이 여러분의 파이톤 프로그램 설계에 도움이 되었으면 합니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.