Erlo

Python多线程使用和注意事项

2019-01-20 01:01:46 发布   278 浏览  
页面报错/反馈
收藏 点赞

多线程

 

基本实现:

第一种,函数方式

# -*- 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]

登录查看全部

参与评论

评论留言

还没有评论留言,赶紧来抢楼吧~~

手机查看

返回顶部

给这篇文章打个标签吧~

棒极了 糟糕透顶 好文章 PHP JAVA JS 小程序 Python SEO MySql 确认