#线程
1.###创建线程
import _thread
import threading
import time
def job():
print("这是一个需要执行的任务")
print("当前线程的个数:", threading.active_count()) #开启线程的个数
print("当前线程信息:", threading.current_thread()) #线程的详细信息
time.sleep(100)
if __name__ == "__main__":
job()
这是一个需要执行的任务
当前线程的个数: 1
当前线程信息: <_MainThread(MainThread, started 140171535042368)>
2.###创建多线程
import _thread
import threading
import time
def job(name):
print("这是一个需要执行的任务")
print(name, time.ctime())
time.sleep(2)
if __name__ == "__main__":
_thread.start_new_thread(job,('thread1', ))
_thread.start_new_thread(job,('thread2', ))
while True:
pass
这是一个需要执行的任务
thread1 Thu Sep 20 21:47:05 2018
这是一个需要执行的任务
thread2 Thu Sep 20 21:47:05 2018
3.###threading模块中通过实例化对象创建多线程
import _thread
import threading
import time
def job(name):
print("这是一个需要执行的任务: %s" %(name))
print("当前线程的个数:", threading.active_count())
print("当前线程信息:", threading.current_thread())
time.sleep(100)
print(name, time.ctime())
if __name__ == "__main__":
job('job0')
t1 = threading.Thread(target=job, name='job1', args=("job1-name",))#target=后接调用函数名,args=连接函数中的参数,name=更改线程的名字 (若函数中只有一个参数,args后括号内的值后面跟',',因为是元组)
t1.start()
t2 = threading.Thread(target=job, name='job2', args=("job2-name",))
t2.start()
这是一个需要执行的任务: job0
当前线程的个数: 1
当前线程信息: <_MainThread(MainThread, started 139794205583168)>
job0 Thu Sep 20 22:04:35 2018
这是一个需要执行的任务: job1-name
当前线程的个数: 2
当前线程信息: <Thread(job1, started 139794079086336)>
这是一个需要执行的任务: job2-name
当前线程的个数: 3
当前线程信息: <Thread(job2, started 139794070693632)>
job1-name Thu Sep 20 22:04:37 2018
job2-name Thu Sep 20 22:04:37 2018
4.###关于join
####join方法: 会等待, 直到运行中的线程执行结束;阻塞正在调用的线程
import threading
import time
def job():
time.sleep(5)
print('job')
t1 = threading.Thread(target=job)
t1.start()
t1.join() # 会等待, 直到t1线程执行结束;阻塞正在调用的线程
t2 = threading.Thread(target=job)
t2.start()
t2.join() # 会等待, 直到t2线程执行结束;阻塞正在调用的线程
####join的应用
import threading
import time
def music(name):
for i in range(2):
print("正在听%s" %(name))
time.sleep(1)
def code(name):
for i in range(2):
print("正在写%s" %(name))
time.sleep(2)
if __name__ == '__main__':
t1 = threading.Thread(target=music, args=("好运来",))
t1.start()
t1.join()#等待t1执行完
t2 = threading.Thread(target=code, args=("爬虫", ))
t2.start()
t2.join()#等待t2执行完成
5.###set_daemon方法
####它的作用是当主线程执行结束时,让没有执行的线程强制结束,即将线程声明为守护线程–set_daemon(True)
import threading
import time
def music(name):
for i in range(2):
print("正在听%s" %(name))
time.sleep(1)
def code(name):
for i in range(2):
print("正在写%s" %(name))
time.sleep(2)
if __name__ == '__main__':
start_time = time.time()
t1 = threading.Thread(target=music, args=("好运来",))
t2 = threading.Thread(target=code, args=("爬虫", ))
# 将t1线程生命为守护线程, 如果设置为True, 子线程启动, 当主线程执行结束, 子线程也结束
# 设置set_Daemon必须在启动线程之前进行设置;
t1.setDaemon(True)
t2.setDaemon(True)
t1.start()
t2.start()
print("花费时间: %s" %(time.time()-start_time))
正在听音乐好运来
正在编写代码爬虫
花费时间: 0.00017547607421875
6.###多线程应用:获取IP地理位置
import json
import threading
from urllib.request import urlopen
import time
def job(ip):
"""获取指定ip对应的地理位置"""
url = "http://ip.taobao.com/service/getIpInfo.php?ip=%s" % (ip)
# 根据url获取网页的内容, 并且解码为utf-8格式, 识别中文;
text = urlopen(url).read().decode('utf-8')
# 将获取的字符串类型转换为字典, 方便处理
d = json.loads(text)['data']
country = d['country']
city = d['city']
print("%s:" %(ip), country, city)
def has_many_thread():
start_time = time.time()
threads = []
ips = ['172.25.254.250', '8.8.8.8',
'172.25.254.250', '8.8.8.8',
'172.25.254.250', '8.8.8.8' ]
for ip in ips:
# 实例化线程对象
t = threading.Thread(target=job, args=(ip, ))
threads.append(t)
# 启动线程执行任务
t.start()
# join方法
[thread.join() for thread in threads]
print("Success, 使用多线程运行时间为:%s" %(time.time()-start_time))
def has_no_thread():
start_time = time.time()
ips = ['172.25.254.250', '8.8.8.8',
'172.25.254.250', '8.8.8.8',
'172.25.254.250', '8.8.8.8']
for ip in ips:
job(ip)
print("Success, 未使用多线程运行时间为:%s" % (time.time() - start_time))
if __name__ == '__main__':
has_many_thread()
has_no_thread()
7.###通过继承方式创建线程
import threading
class Thread(threading.Thread):
def __init__(self, jobname):
super(IpThread, self).__init__()#声明为父类函数
self.jobname = jobname
def run(self): # 将多线程需要执行的任务重写到run方法中;
print("this is a job")
t1 = IpThread(jobname="new job")
t1.start()
8.###线程锁:因为多线程是中的各个线程是同时工作运行的,所以当对其中某个线程中的数据作出改动时,会出现未知的错误,此时就需要线程锁来控制被修改数据
####用以下例子来说明线程锁的作用
#####不用线程锁
import threading
def add(lock):
global money
for i in range(1000000):
money+=1
def reduce(lock):
global money
for i in range(1000000):
money-=1
if __name__=='__main__':
money=0
lock=threading.Lock()
t1=threading.Thread(target=add,args=(lock,))
t2=threading.Thread(target=reduce,args=(lock,))
t1.start()
t2.start()
t1.join()
t2.join()
print("最终金额为:%s"%(money))
最终金额为:452364 # 结果本应该是零,因为没有线程锁,会出现错误
#####使用线程锁
import threading
def add(lock):
lock.acquire()#上锁
global money
for i in range(10000):
money+=1
lock.release()#释放
def reduce(lock):
lock.acquire()
global money
for i in range(10000):
money-=1
lock.release()
if __name__=='__main__':
money=0
lock=threading.Lock()
t1=threading.Thread(target=add,args=(lock,))
t2=threading.Thread(target=reduce,args=(lock,))
t1.start()
t2.start()
t1.join()
t2.join()
print("最终金额为:%s"%(money))
最终金额为:0 #结果始终为0
9.###队列与多线程
####因为多线程在执行后会产生数据,但它并不能返回任务执行结果,可以用队列来存储多线程产生的数据
import threading
from collections import Iterable
from mytimeit import timeit
from queue import Queue
def job(l, queue):
# 将任务的结果存储到队列中;
queue.put(sum(l))
@timeit
def use_thread():
# 实例化一个队列, 用来存储每个线程执行的结果;
q = Queue()
# # 入队
# q.put(1)
li = [[1,2,3,4,5], [2,3,4,5,6], [2,3,4,5,6,7,8], [2,3,4,5,6]]
threads = []
for i in li:
t = threading.Thread(target=job, args=(i, q))
threads.append(t)
t.start()
# join方法等待所有子线程之心结束
[thread.join() for thread in threads]
# 从队列里面拿出所有的运行结果
result = [q.get() for _ in li]
print(result)
# print(isinstance(q, Iterable))
if __name__ == "__main__":
use_thread()
[15, 20, 35, 20]
use_thread执行时间0.0006349086761474609
10.###线程池:存放多个线程单位,同时有着对应的任务队列,在执行过程中就是使用线程池中已有的有限线程作完任务,它的好处就是不必对每一个任务都创建一个线程,节省了工作时间,减少了工作量(python3.2之后才可以使用)
def job():
print("this is a job")
return "hello"
if __name__ == '__main__':
pool = ThreadPoolExecutor(max_workers=10)# 实例化对象, 线程池包含10个线程来处理任务;
# 往线程池里面扔需要执行的任务, 返回一个对象,( _base.Future实例化出来的)
f1 = pool.submit(job)
f2 = pool.submit(job)
# 判断任务是否执行结束
print(f1.done())
time.sleep(1)
print(f2.done())
# 获取任务执行的结果
print(f1.result())
print(f2.result())
11.###线程池与map函数
from urllib.error import HTTPError
from urllib.request import urlopen
from concurrent.futures import ThreadPoolExecutor
from concurrent.futures import as_completed
import time
URLS = ['http://httpbin.org', 'http://example.com/',
'https://api.github.com/'] * 10
def get_page(url, timeout=3):
try:
content = urlopen(url).read()
return {'url':url, 'len':len(content)}
except HTTPError as e:
return {'url':url, 'len':0}
pool = ThreadPoolExecutor(max_workers=20)
for res in pool.map(get_page, URLS):
print(res)