import threading
import time
num = 0
def task_thread(n):
global num
for i in range(1000000):
num = num + n
num -= n
t1 = threading.Thread(target=task_thread, args=(6,))
t2 = threading.Thread(target=task_thread, args=(17,))
t3 = threading.Thread(target=task_thread, args=(11,))
t1.start()
t2.start()
t3.start()
t1.join()
t2.join()
t3.join()
print(num)
执行结果:多次执行,发现出现结果为 -11 ,正确结果应该是0
-11
import threading
import time
num = 0
def task_thread(n, lock):
global num
lock.acquire()
for i in range(1000000):
num = num + n
num -= n
lock.release()
lock = threading.Lock()
t1 = threading.Thread(target=task_thread, args=(6, lock))
t2 = threading.Thread(target=task_thread, args=(17, lock))
t3 = threading.Thread(target=task_thread, args=(11, lock))
t1.start()
t2.start()
t3.start()
t1.join()
t2.join()
t3.join()
print(num)
执行结果:多试了几次,结果都是正确的
0
import threading
import time
import random
# 模拟最多5人同时办理业务
semaphore = threading.BoundedSemaphore(5)
# 模拟银行办理业务
def yewubanli(name):
# 因为在同一个进程中
semaphore.acquire()
time.sleep(random.randint(1, 3))
print(f'{time.strftime("%Y-%m-%d %H:%M:%S")} {name} 正在办理业务')
semaphore.release()
thread_list = []
for i in range(10):
t = threading.Thread(target=yewubanli, args=(f'客户_{i}',))
thread_list.append(t)
t.start()
for i in thread_list:
i.join()
执行结果:同一时刻,最多5个线程在执行
2021-05-20 11:10:17 客户_4 正在办理业务
2021-05-20 11:10:17 客户_3 正在办理业务
2021-05-20 11:10:18 客户_1 正在办理业务
2021-05-20 11:10:18 客户_2 正在办理业务
2021-05-20 11:10:18 客户_5 正在办理业务
2021-05-20 11:10:19 客户_0 正在办理业务
2021-05-20 11:10:19 客户_7 正在办理业务
2021-05-20 11:10:19 客户_8 正在办理业务
2021-05-20 11:10:19 客户_9 正在办理业务
2021-05-20 11:10:20 客户_6 正在办理业务
Process finished with exit code 0
import threading
class Boy(threading.Thread):
def __init__(self, cond ,name):
super().__init__()
self.cond = cond
self.name = name
def run(self):
self.cond.acquire()
print(self.name + ': 嫁给我吧!')
# 唤醒一个挂起的线程,让韩梅梅表态(唤醒的是Girl类中wait()的线程)
self.cond.notify()
# 释放内部占用的锁,同时线程被挂起,直至接收到通知被唤醒或者超时,等待韩梅梅回答
self.cond.wait()
print(self.name + ': 单膝跪下,送上戒指!!')
self.cond.notify()
self.cond.wait()
print(self.name + ': 太太,你的选择太明智了')
self.cond.release()
class Girl(threading.Thread):
def __init__(self, cond, name):
super().__init__()
self.name = name
self.cond = cond
def run(self):
self.cond.acquire()
# 等待李磊的求婚
self.cond.wait()
print(self.name +': 没有情调,不够浪漫,不答应')
self.cond.notify()
self.cond.wait()
print(self.name + ': 好的,答应你了')
self.cond.notify()
self.cond.release()
cond = threading.Condition()
boy = Boy(cond, "李磊")
girl = Girl(cond, "韩梅梅")
girl.start()
boy.start()
执行结果:
李磊: 嫁给我吧!
韩梅梅: 没有情调,不够浪漫,不答应
李磊: 单膝跪下,送上戒指!!
韩梅梅: 好的,答应你了
李磊: 太太,你的选择太明智了
在上述示例中:
1.程序实例化一个Conditon对象cond,一个Boy对象boy,一个Girl对象girl。
2.程序先启动girl线程,girl 线程获取了条件变量锁 cond,但是又执行了 wait()并释放了条件变量锁,自身进入阻塞状态;
3. boy线程启动后,就获得了条件变量锁 cond 并发出了消息,之后通过notify 唤醒一个挂起的线程,并释放条件变量锁,等待 girl 的回答。
4. 后面的过程都是重复这些步骤,最后通过release程序释放资源。
这个例子不怎么好,执行结果可能会不一致
import threading, time
class Boy(threading.Thread):
def __init__(self, cond, name):
super().__init__()
self.cond = cond
self.name = name
def run(self):
print(self.name + ': 嫁给我把')
# 唤醒一个挂起的线程,等待韩梅梅表态
self.cond.set()
time.sleep(0.5)
self.cond.wait()
print(self.name + ': 单膝跪下,送上戒指')
self.cond.set()
time.sleep(0.5)
self.cond.wait()
self.cond.clear()
print(self.name + ": 太太,你太明智了")
class Girl(threading.Thread):
def __init__(self, cond, name):
super().__init__()
self.name = name
self.cond = cond
def run(self):
# 等待李磊的求婚
self.cond.wait()
print(self.name +': 没有情调,不够浪漫,不答应')
self.cond.set()
time.sleep(0.5)
self.cond.wait()
print(self.name + ': 好的,答应你了')
self.cond.set()
cond = threading.Event()
boy = Boy(cond, "李磊")
girl = Girl(cond, "韩梅梅")
girl.start()
boy.start()
执行结果:
李磊: 嫁给我把
韩梅梅: 没有情调,不够浪漫,不答应
李磊: 单膝跪下,送上戒指
韩梅梅: 好的,答应你了
李磊: 太太,你太明智了
Event 内部默认设置了一个标志,初始值为False。
上述代码中对象girl通过 wait() 方法进入等待状态,直到对象boy调用该 Event 的 set() 方法将内置的标志设置为True时,对象girl再继续运行。
对象boy最后调用 Event 的 clear() 方法 再将内置标志设置为 False,恢复初始状态。
import threading
import time
import queue
# 先进先出
q = queue.Queue(maxsize=5)
# q = queue.LifoQueue(maxsize=3) # 后入先出
# q = queue.PriorityQueue(maxsize=3) # 优先级
def Producer_A():
count = 1
while True:
q.put(f"包子_{count}")
print(f"{time.strftime('%H:%M:%S')} A 生产了: [包子_{count}]")
count += 1
time.sleep(1)
def Consumer_B():
while 1:
print(f"{time.strftime('%H:%M:%S')} B 吃了: [{q.get()}]")
time.sleep(3)
def Consumer_C():
while 1:
print(f"{time.strftime('%H:%M:%S')} C 吃了: [{q.get()}]")
time.sleep(5)
a = threading.Thread(target=Producer_A)
b = threading.Thread(target=Consumer_B)
c = threading.Thread(target=Consumer_C)
a.start()
b.start()
c.start()
执行结果
16:30:04 A 生产了: [包子_1]
16:30:04 B 吃了: [包子_1]
16:30:05 A 生产了: [包子_2]
16:30:04 C 吃了: [包子_2]
16:30:06 A 生产了: [包子_3]
16:30:07 A 生产了: [包子_4]
16:30:08 C 吃了: [包子_3]
16:30:08 A 生产了: [包子_5]
16:30:09 B 吃了: [包子_4]
16:30:09 A 生产了: [包子_6]
……
from multiprocessing.dummy import Pool as ThreadPool
import time
def fun(n):
time.sleep(2)
start = time.time()
for i in range(5):
fun(i)
print(f'单线程执行耗时: {time.time() - start}')
start2 = time.time()
# 开5个worker线程,没有参数时表示默认cou的核心数
pool = ThreadPool(5)
# pool = ThreadPool(processes=5)
# # 在线程中执行urllib2.urlopen(url),并且返回执行结果
# result2 = pool.map(func, range(5)) # 相当于执行了下面的for循环
for i in range(5):
pool.apply_async(func=fun, args=(i,))
pool.close()
pool.join()
print(f"线程池(5)并发执行耗时:{time.time() - start2}")
执行结果
单线程执行耗时: 10.002147674560547
线程池(5)并发执行耗时:2.0186564922332764
Process finished with exit code 0
from concurrent.futures import ThreadPoolExecutor
import threading
import time
def func(max):
num = 0
for i in range(max):
print(threading.current_thread().name + ' ' + str(i))
num += i
return my_sum
# 创建一个包含2条线程的线程池
with ThreadPoolExecutor(max_workers=2) as pool:
# 向线程池提交一个task, 50会作为action()函数的参数
future1 = pool.submit(action, 50)
# 向线程池再提交一个task, 100会作为action()函数的参数
future2 = pool.submit(func, 100)
def get_result(future):
print(future.result())
# 为future1添加线程完成的回调函数
future1.add_done_callback(get_result)
# 为future2添加线程完成的回调函数
future2.add_done_callback(get_result)
浏览器的工作原理:
爬虫原理:
'''
requests模块是第三方模块,需要下载,
方法1:cmd命令下载:pip install requests
方法2:pycharm中安装:File --> Settings --> Project:project01 --> Project Interpreter --> pip --> 搜索需要下载的模块 -->点击 install
'''
import requests
ret = requests.get('http://www.baidu.com')
if ret.status_code == 200:
print(ret.text)
输出结果:获取到源码
<!DOCTYPE html>=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>ç™¾åº¦ä¸€ä¸‹ï¼Œä½ å°±çŸ¥é“</title></head> <body link=#0000cc>