欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Python多线程使用和注意事项

程序员文章站 2024-01-24 11:01:46
多线程 基本实现: 第一种,函数方式 # -*- coding:utf-8 -*- import thread import time def print_time(threadName, delay): count = 0 while count < 5: time.sleep(delay) co ......
多线程
 
基本实现:
第一种,函数方式
# -*- 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]