• Python多线程使用和注意事项


    多线程
     
    基本实现:
    第一种,函数方式
    # -*- 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]
  • 相关阅读:
    用goto做异常处理
    零长度数组的妙用
    DTMF三种模式(SIPINFO,RFC2833,INBAND)
    Myeclipse下的struts2.3.8 配置 保证绝对好用
    Linux内核--内核数据类型
    Linux内核:kthread_create(线程)、SLEEP_MILLI_SEC
    3.4.4 数据预留和对齐(skb_reserve, skb_push, skb_put, skb_pull)
    Linux 2.6内核中新的锁机制--RCU
    Linux中SysRq的使用(魔术键)
    CentOS Linux服务器安全设置
  • 原文地址:https://www.cnblogs.com/xuyiqing/p/10293833.html
Copyright © 2020-2023  润新知