多線程
基本實現:
第一種,函數方式
# -*- coding:utf-8 -*-
import thread
import time
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,))
except:
print "Error!Unable to start thread."
while 1:
pass
第二種,繼承父類
# -*- coding:utf-8 -*-
import threading
import time
class MyThread(threading.Thread):
def __init__(self, thread_id, name, counter):
threading.Thread.__init__(self)
self.thread_id = thread_id
self.name = name
self.counter = counter
def run(self):
print "Starting:" + self.name
print_time(self.name, self.counter, 5)
print "Exiting:" + self.name
def print_time(thread_name, delay, counter):
while counter:
time.sleep(delay)
print '%s : %s' % (thread_name, time.ctime(time.time()))
counter -= 1
thread1 = MyThread(1, "Thread-1", 1)
thread2 = MyThread(2, "Thread-2", 2)
thread1.start()
thread2.start()
線程同步的問題解決:鎖
這里第一個線程執行的時候,第二個線程是等待狀態的
# -*- coding:utf-8 -*-
import threading
import time
threadLock = threading.Lock()
threads = []
class MyThread(threading.Thread):
def __init__(self, thread_id, name, counter):
threading.Thread.__init__(self)
self.thread_id = thread_id
self.name = name
self.counter = counter
def run(self):
print "Starting:" + self.name
threadLock.acquire()
print_time(self.name, self.counter, 5)
print "Exiting:" + self.name
threadLock.release()
def print_time(thread_name, delay, counter):
while counter:
time.sleep(delay)
print '%s : %s' % (thread_name, time.ctime(time.time()))
counter -= 1
thread1 = MyThread(1, "Thread-1", 1)
thread2 = MyThread(2, "Thread2", 2)
thread1.start()
thread2.start()
threads.append(thread1)
threads.append(thread2)
for thread in threads:
thread.join()
線程優先級隊列:
雖然開啟了多個線程,不過打印順序一定是:one按順序到five
# -*- coding:utf-8 -*-
import threading
import time
import Queue
exit_flag = 0
queue_lock = threading.Lock()
work_queue = Queue.Queue(10)
thread_list = ["Thread-1", "Thread-2", "Thread-3"]
name_list = ["one", "two", "three", "four", "five"]
threads = []
thread_id = 1
class MyThread(threading.Thread):
def __init__(self, thread__id, name, queue):
threading.Thread.__init__(self)
self.thread__id = thread__id
self.name = name
self.queue = queue
def run(self):
print "Starting:" + self.name
process_data(self.name, self.queue)
print "Exiting:" + self.name
def process_data(thread_name, queue):
while not exit_flag:
queue_lock.acquire()
if not work_queue.empty():
data = queue.get()
queue_lock.release()
print "%s processing %s" % (thread_name, data)
else:
queue_lock.release()
time.sleep(2)
for t in thread_list:
thread = MyThread(thread_id, t, work_queue)
thread.start()
threads.append(thread)
thread_id += 1
queue_lock.acquire()
for word in name_list:
work_queue.put(word)
queue_lock.release()
while not work_queue.empty():
pass
exit_flag = 1
for t in threads:
t.join()
這里的join函數重點解釋下:
join的原理就是依次檢驗線程池中的線程是否結束,沒有結束就阻塞主線程直到其他線程結束,如果結束則跳轉執行下一個線程的join函數
接下來看看多線程實際的案例:
多線程訪問網站
# -*- coding:utf-8 -*-
import urllib2
import time
from threading import Thread
class GetUrlThread(Thread):
def __init__(self, url):
Thread.__init__(self)
self.url = url
def run(self):
response = urllib2.urlopen(self.url)
print self.url, response.getcode()
def get_responses():
urls = [
'https://www.baidu.com',
'https://www.taobao.com',
'https://www.cnblogs.com',
'https://github.com',
'https://www.jd.com'
]
start = time.time()
threads = []
for url in urls:
thread = GetUrlThread(url)
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
print "Time: % s" % (time.time() - start)
get_responses()
如果多個線程訪問同一個變量,容易出問題,比如下面:
有可能最后的實際值並不是50
# -*- coding:utf-8 -*-
from threading import Thread
some_var = 0
class IncrementThread(Thread):
def run(self):
global some_var
read_value = some_var
print "線程%s中的some_var是%d" % (self.name, read_value)
some_var = read_value + 1
print "線程%s中的some_var增加后變成%d" % (self.name, some_var)
def use_increment_thread():
threads = []
for i in range(50):
thread = IncrementThread()
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
print "在50次運算后some_var應該變成50"
print "在50次運算后some_var實際值為:%d" % (some_var,)
use_increment_thread()
解決辦法,加入一個鎖:
這種情況,最后的實際值一定是50
# -*- coding:utf-8 -*-
from threading import Thread, Lock
lock = Lock()
some_var = 0
class IncrementThread(Thread):
def run(self):
global some_var
lock.acquire()
read_value = some_var
print "線程%s中的some_var是%d" % (self.name, read_value)
some_var = read_value + 1
print "線程%s中的some_var增加后變成%d" % (self.name, some_var)
lock.release()
def use_increment_thread():
threads = []
for i in range(50):
thread = IncrementThread()
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
print "在50次運算后some_var應該變成50"
print "在50次運算后some_var實際值為:%d" % (some_var,)
use_increment_thread()
另一個鎖的案例:
不加鎖容易出事
# -*- coding:utf-8 -*-
from threading import Thread
import time
class CreateListThread(Thread):
def __init__(self):
self.entries = []
Thread.__init__(self)
def run(self):
self.entries = []
for i in range(10):
time.sleep(1)
self.entries.append(i)
print self.entries
def use_create_list_thread():
for i in range(3):
t = CreateListThread()
t.start()
use_create_list_thread()
結果:
[[[000, , , 111, , , 222, , , 333, , , 444, , , 555, , , 666, , , 777, , , 888, , , 999]]]
給他加上鎖:
# -*- coding:utf-8 -*-
from threading import Thread, Lock
import time
lock = Lock()
class CreateListThread(Thread):
def __init__(self):
self.entries = []
Thread.__init__(self)
def run(self):
self.entries = []
for i in range(10):
time.sleep(1)
self.entries.append(i)
lock.acquire()
print self.entries
lock.release()
def use_create_list_thread():
for i in range(3):
t = CreateListThread()
t.start()
use_create_list_thread()
結果:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]