멀티스레딩은 동시에 여러 프로그램을 실행하는 것과 유사합니다. 멀티스레딩에는 다음과 같은 장점이 있습니다.
스레드를 사용하면 장기 프로그램의 작업을 백그라운드로 처리할 수 있습니다.
사용자 인터페이스가 더욱 매력적일 수 있으므로 사용자가 버튼을 클릭하여 특정 이벤트 처리를 시작하면 진행률 표시줄이 팝업되어 처리 진행 상황을 표시할 수 있습니다.
프로그램의 실행 속도가 빨라질 수 있습니다
스레드는 사용자 입력, 파일 읽기 및 쓰기, 네트워크 데이터 송수신과 같은 일부 대기 작업을 구현하는 데 더 유용합니다. 이 경우 메모리 사용량 등과 같은 일부 귀중한 리소스를 해제할 수 있습니다.
스레드는 실행 중인 프로세스와 여전히 다릅니다. 각각의 독립 스레드에는 프로그램 실행을 위한 진입점, 순차적 실행 시퀀스 및 프로그램 종료점이 있습니다. 그러나 스레드는 독립적으로 실행될 수 없으며 응용 프로그램 내에 존재해야 하며 응용 프로그램은 다중 스레드 실행 제어를 제공합니다.
각 스레드에는 스레드 컨텍스트라고 하는 고유한 CPU 레지스터 세트가 있으며, 이는 스레드가 마지막으로 실행되었을 때 CPU 레지스터의 상태를 반영합니다.
명령 포인터와 스택 포인터 레지스터는 스레드 컨텍스트에서 가장 중요한 두 가지 레지스터입니다. 스레드는 항상 프로세스 컨텍스트에서 실행됩니다. 이 주소는 소유한 프로세스의 주소 공간에 메모리를 표시하는 데 사용됩니다. 스레드.
스레드를 선점(중단)할 수 있습니다.
다른 스레드가 실행 중인 동안 스레드가 일시적으로 보류(휴면이라고도 함)될 수 있습니다. 이를 스레드 백오프라고 합니다.
Python 스레드 학습 시작
Python에서 스레드를 사용하는 방법에는 두 가지가 있습니다. 스레드 개체를 래핑하는 함수 또는 클래스입니다.
기능: 스레드 모듈에서 start_new_thread() 함수를 호출하여 새 스레드를 생성합니다. 구문은 다음과 같습니다.
thread.start_new_thread( function, args[, kwargs] )
매개변수 설명:
기능 - 스레드 기능.
args - 스레드 함수에 전달되는 매개변수는 튜플 유형이어야 합니다.
kwargs - 선택적 매개변수입니다.
인스턴스:
#!/usr/bin/python
스레드 가져오기
가져오기 시간
# 스레드에 대한 함수 정의
def print_time(threadName, Delay):
count = 0
while count < 5:
time.sleep(delay)
count += 1
print "%s: %s" % ( threadName, time .ctime(time.time()) )
# 스레드 두 개 만들기
try:
thread.start_new_thread( print_time, ("Thread -1", 2, ) )
thread.start_new_thread( print_time, ("Thread-2", 4, ) )
제외:
print "오류: 불가능 to start thread"
while 1:
pass
위 실행 결과 프로그램은 다음과 같습니다 :
Thread-1: Thu Jan 22 15:42:17 2009
Thread-1: Thu Jan 22 15 :42:19 2009
스레드-2: 1월 22일 목요일 15:42:19 2009
스레드-1: 2009년 1월 22일 목요일 15:42:21
스레드 -2: 2009년 1월 22일 목요일 15:42:23
스레드-1: 2009년 1월 22일 목요일 15:42:23
스레드-1: 2009년 1월 22일 목요일 15:42:25
스레드 2: 2009년 1월 22일 목요일 15:42:27
스레드 2: 2009년 1월 22일 목요일 15:42:31
스레드 2: 1월 목요일 22 15:42 :35 2009
스레드의 끝은 일반적으로 스레드 함수의 자연스러운 끝에 따라 달라집니다. thread.exit()를 호출할 수도 있습니다. SystemExit 예외를 발생시키는 스레드 함수에서 스레드 종료 목적을 달성합니다.
스레딩 모듈
Python은 스레드와 스레딩이라는 두 가지 표준 라이브러리를 통해 스레드를 지원합니다. 스레드는 낮은 수준의 기본 스레드와 간단한 잠금을 제공합니다.
스레드 모듈에서 제공하는 기타 메서드:
threading.currentThread(): 현재 스레드 변수를 반환합니다.
threading.enumerate(): 실행 중인 스레드가 포함된 목록을 반환합니다. 실행은 시작 전과 종료 후 스레드를 제외하고 시작 후 종료 전 스레드를 나타냅니다.
threading.activeCount(): 실행 중인 스레드 수를 반환하며, 이는 len(threading.enumerate())과 동일한 결과를 갖습니다.
스레드 모듈은 사용 메서드 외에도 스레드를 처리하기 위한 Thread 클래스도 제공합니다. Thread 클래스는 다음 메서드를 제공합니다.
run(): 스레드 활동을 나타내는 데 사용되는 메서드입니다.
start(): 스레드 활동을 시작합니다.
join([time]): 스레드가 종료될 때까지 기다립니다. 이는 스레드의 Join() 메소드가 abort(정상적으로 종료하거나 처리되지 않은 예외 발생)를 호출하거나 선택적 시간 초과가 발생할 때까지 호출 스레드를 차단합니다.
isAlive(): 스레드가 활성 상태인지 여부를 반환합니다.
getName(): 스레드 이름을 반환합니다.
setName(): 스레드 이름을 설정합니다.
Threading 모듈을 사용하여 스레드 생성
Threading 모듈을 사용하여 스레드를 생성하고 threading.Thread에서 직접 상속한 다음 __init__ 메서드를 재정의하고 메서드를 실행합니다.
#!/usr/bin/python
가져오기 스레딩
가져오기 시간
exitFlag = 0
class myThread(threading.Thread): #부모 클래스 threading.Thread 상속
def __init__(self, threadID, 이름, 카운터):
거기에 없었습니다 — —( 있었던 적이 있었습니다 -- 있었습니다 🎜>
def run(self): # 실행될 코드를 실행 함수에 작성합니다 . 스레드는 생성 후 바로 실행 기능을 실행합니다 print "Starting" + self.name print_time( self.name, self.counter, 5) print "종료" + self.name def print_time(threadName, Delay, counter): while counter: ifexitFlag:thread.exit() time.sleep(delay) print "%s: %s " % (threadName, time.ctime(time.time())) counter -= 1 # 새 스레드 만들기thread1 = myThread(1, "Thread-1", 1)thread2 = myThread(2, "Thread-2", 2) # 스레드 시작
thread1.start()thread2. start() print "Main Thread 종료" 위 프로그램 실행 결과는 다음과 같습니다. Thread-1 시작Thread-2 시작메인 스레드 종료Thread-1: 목 Mar 21 09:10:03 2013Thread-1: Thu Mar 21 09:10:04 2013Thread-2: Thu Mar 21 09:10:04 2013스레드-1: 2013년 3월 21일 목요일 09:10:05스레드-1: 2013년 3월 21일 목요일 09:10:06
스레드 2: 3월 21일 목요일 09:10 :06 2013Thread-1: Thu Mar 21 09:10:07 2013Thread-1 종료Thread-2: Thu Mar 21 09:10:08 2013Thread-2: Thu Mar 21 09:10:10 2013Thread-2: Thu Mar 21 09:10: 12 2013Thread-2 종료 스레드 동기화여러 스레드가 공동으로 특정 데이터를 수정하는 경우, 데이터의 정확성을 보장하기 위해 예측할 수 없는 결과가 발생할 수 있습니다. 여러 스레드를 동기화해야 합니다. 간단한 스레드 동기화를 위해 Thread 객체의 Lock 및 Rlock을 사용합니다. 두 객체 모두 한 번에 하나의 스레드에서만 작동해야 하는 데이터의 경우 획득 방법 사이에 배치할 수 있습니다. 및 릴리스 방법. 멀티스레딩의 장점은 동시에 여러 작업을 실행할 수 있다는 것입니다(적어도 그렇게 느껴집니다). 그러나 스레드가 데이터를 공유해야 하는 경우 데이터가 동기화되지 않는 문제가 발생할 수 있습니다. 이런 상황을 생각해 보세요. 목록의 모든 요소가 0이고, "set" 스레드는 모든 요소를 뒤에서 앞으로 1로 변경하며, "print" 스레드는 목록을 앞에서 뒤로 읽고, 인쇄. 그런 다음 "set" 스레드가 변경되기 시작하면 "print" 스레드가 목록을 인쇄하고 출력은 0과 1의 절반이 됩니다. 이것이 데이터의 비동기화입니다. 이러한 상황을 방지하기 위해 잠금 개념이 도입되었습니다. 잠금에는 잠김과 잠금 해제의 두 가지 상태가 있습니다. "set"과 같은 스레드가 공유 데이터에 액세스하려고 할 때마다 먼저 잠금을 획득해야 합니다. "print"와 같은 다른 스레드가 이미 잠금을 획득한 경우 "set" 스레드가 일시 중지되도록 해야 합니다. 이는 동기식 차단입니다. 스레드 " Print "가 액세스가 완료되고 잠금이 해제된 후 스레드 "설정"이 계속되도록 합니다. 이러한 처리를 거쳐 목록을 인쇄할 때 모두 0 또는 모두 1이 출력되며, 반은 0이고 반은 1인 민망한 장면은 더 이상 발생하지 않습니다. 인스턴스: #!/usr/bin/python 스레딩 가져오기가져오기 시간
class myThread(threading.Thread):
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = 이름
self.counter = counter
def run(self):
Print "Starting"+Self.name
#获 p p p p p p p p True
#선택적 Timeout 매개변수를 반환한 후 잠금이 해제될 때까지 차단됩니다.
# 그렇지 않으면 False가 됩니다. 시간 초과 후 반환됨 🎜> threadLock.release()
def print_time(threadName, Delay, counter):
while counter:
time.sleep (지연)
인쇄 "%s: %s" % (threadName, time.ctime(time.time()))
카운터 -= 1
threadLock = threading.Lock()
threads = []
# 새 스레드 만들기
thread1 = myThread(1, "Thread-1 ", 1)
thread2 = myThread(2, "Thread-2", 2)
# 새 스레드 시작
thread1.start( )
thread2.start()
# 스레드 목록에 스레드 추가
threads.append(thread1)
threads.append(thread2)
# 모든 스레드가 완료될 때까지 기다립니다
for t in thread:
t.join()
"메인 스레드 종료" 인쇄
스레드 우선순위 대기열(Queue)
Python의 대기열 모듈은 동기 스레드를 제공합니다. -safe queue 클래스에는 FIFO(선입선출) 대기열 대기열, LIFO(후입선출) 대기열 LifoQueue 및 우선순위 대기열 PriorityQueue가 포함됩니다. 이러한 대기열은 잠금 기본 형식을 구현하며 다중 스레드에서 직접 사용할 수 있습니다. 대기열을 사용하여 스레드 간 동기화를 달성할 수 있습니다.
큐 모듈의 일반적인 메소드:
Queue.qsize()는 큐의 크기를 반환합니다.
Queue.empty() 비어 있으면 True를 반환하고, 그렇지 않으면 False를 반환합니다
Queue.full() 대기열이 가득 차면 True를 반환하고, 그렇지 않으면 False를 반환합니다.
Queue.full은 최대 크기 크기에 해당합니다
Queue.get([ block[, timeout]]) 대기열 가져오기, 시간 초과 대기 시간
Queue.get_nowait()는 Queue.get(False)
Queue.put(item과 동일합니다. ) 대기열에 쓰기, 시간 초과 대기 시간
Queue.put_nowait(item)은 Queue.put(item, False)
Queue.task_done()과 동일합니다. 작업을 완료한 후 대기열 .task_done() 함수는 완료된 작업에 메시지를 반환합니다.
Queue.join()은 실제로 다른 작업을 수행하기 전에 대기열이 빌 때까지 기다리는 것을 의미합니다
예:
#!/usr/bin/python
가져오기 대기열
가져오기 스레딩
가져오기 시간
exitFlag = 0
class myThread(threading.Thread):
def __init__(self, threadID, 이름, q):
스레드가 없었습니다. 🎜> def run(self):
print "Starting" + self. name
process_data(self.name, self.q)
print "Exiting " + self.name
def process_data(threadName, q) :
exitFlag가 아닌 경우:
queueLock.acquire()
workQueue.empty():
data = q.get()
queueLock.release()
인쇄 "%s 처리 중 %s" % (스레드 이름, 데이터)
else:
queueLock.release()
time.sleep(1 )
threadList = ["Thread-1", "Thread-2", "Thread-3"]
nameList = ["One", "Two", "Three ", "4", "5"]
queueLock = threading.Lock()
workQueue = Queue.Queue(10)
스레드 = []
threadID = 1
# 创建新线程
for tName in threadList:
thread = myThread(threadID, tName, workQueue)
thread.start()
threads.append(thread)
threadID += 1
# 填充队列
queueLock.acquire()
nameList의 단어:
workQueue.put(word)
queueLock.release()
# 等待队列清空
workQueue.empty()가 아닌 동안:
pass
# 통지线程是时候退출
exitFlag = 1
# 等待所有线程完成
t in 스레드의 경우:
t.join()
print '메인 스레드 종료 중'
以上程序执行结果:
스레드-1 시작
Thread-2 시작
Thread-3 시작
Thread-1 처리 One
Thread-2 처리 Two
Thread-3 처리 Three
스레드-1 처리 4개
스레드 2 처리 5개
스레드-3 종료
스레드 1 종료
스레드 종료- 2
메인 스레드 종료