Python之线程
1.线程简介(1)线程概念(2)线程与进程
2.线程的格式(1)格式(2)主要参数(3)常用方法
3.线程的创建示例(1)不设置线程名、被调函数不需要传参(2)设置线程名、被调函数需要传参(3)不写 join()方法(4)守护线程
4.锁线程实例(1)不加锁(2)加锁
1.线程简介
(1)线程概念
线程是指进程内的一个执行单元,也是进程内的可调度实体;相当于是进程的一个子任务是操作系统能够进行运算调度的最小单位
(2)线程与进程
一个程序中至少有一个进程,而一个进程中也至少有一个线程
2.线程的格式
(1)格式
import threading
threading
.Thread
(target
=None, name
=None, args
=())
(2)主要参数
参数名作用
target需要调用的函数名name设置线程的名字args被调用函数所需要的参数(以元组的形式传入)
(3)常用方法
方法名功能
start()启动线程join()等待子线程结束setName()设置线程名getName()返回线程名setDaemon()设置守护线程
3.线程的创建示例
(1)不设置线程名、被调函数不需要传参
import threading
import time
def task1():
print(threading
.current_thread
().name
,2)
for i
in range(1,6):
time
.sleep
(2)
print("*****我采摘%s个苹果"%i
)
def task2():
print(threading
.current_thread
().name
, 3)
for i
in range(1,6):
time
.sleep
(2)
print("$$$$$我采摘%s个苹果"%i
)
print(threading
.current_thread
().name
,0)
print(time
.ctime
())
per1
=threading
.Thread
(target
=task1
)
per2
=threading
.Thread
(target
=task2
)
per1
.start
()
per2
.start
()
per1
.join
()
per2
.join
()
print(time
.ctime
())
print(threading
.current_thread
().name
,1)
MainThread
0
Fri Jul
3 16:53:59 2020
Thread
-1 2
Thread
-2 3
*****我采摘
1个苹果
$$$$$我采摘
1个苹果
*****我采摘
2个苹果
$$$$$我采摘
2个苹果
*****我采摘
3个苹果
$$$$$我采摘
3个苹果
$$$$$我采摘
4个苹果
*****我采摘
4个苹果
$$$$$我采摘
5个苹果
*****我采摘
5个苹果
Fri Jul
3 16:54:09 2020
MainThread
1
(2)设置线程名、被调函数需要传参
被调函数参数需要以元组形式传入,否则会出错
import threading
import time
def task1(a
):
print(threading
.current_thread
().name
,2,a
)
for i
in range(1,6):
time
.sleep
(2)
print("*****我采摘%s个苹果"%i
)
def task2():
print(threading
.current_thread
().name
, 3)
for i
in range(1,6):
time
.sleep
(2)
print("$$$$$我采摘%s个苹果"%i
)
print(threading
.current_thread
().name
,0)
print(time
.ctime
())
per1
=threading
.Thread
(target
=task1
,name
="线程1",args
=(10,))
per2
=threading
.Thread
(target
=task2
)
per2
.setName
("线程2")
per1
.start
()
per2
.start
()
per1
.join
()
per2
.join
()
print(time
.ctime
())
print(threading
.current_thread
().name
,1)
MainThread
0
Fri Jul
3 17:58:03 2020
线程
1 2 10
线程
2 3
*****我采摘
1个苹果
$$$$$我采摘
1个苹果
*****我采摘
2个苹果
$$$$$我采摘
2个苹果
*****我采摘
3个苹果
$$$$$我采摘
3个苹果
*****我采摘
4个苹果
$$$$$我采摘
4个苹果
*****我采摘
5个苹果
$$$$$我采摘
5个苹果
Fri Jul
3 17:58:13 2020
MainThread
1
(3)不写 join()方法
主线程不会等待子线程结束,当主线程执行完自己的任务就直接结束,而子线程继续执行自己的任务
import threading
import time
def task1(a
):
print(threading
.current_thread
().name
,2,a
)
for i
in range(1,6):
time
.sleep
(2)
print("*****我采摘%s个苹果"%i
)
def task2():
print(threading
.current_thread
().name
, 3)
for i
in range(1,6):
time
.sleep
(2)
print("$$$$$我采摘%s个苹果"%i
)
print(threading
.current_thread
().name
,0)
print(time
.ctime
())
per1
=threading
.Thread
(target
=task1
,name
="线程1",args
=(10,))
per2
=threading
.Thread
(target
=task2
)
per2
.setName
("线程2")
per1
.start
()
per2
.start
()
print(time
.ctime
())
print(threading
.current_thread
().name
,1)
MainThread
0
Fri Jul
3 18:19:31 2020
线程
1 2 10
线程
2 3
Fri Jul
3 18:19:31 2020
MainThread
1
*****我采摘
1个苹果
$$$$$我采摘
1个苹果
*****我采摘
2个苹果
$$$$$我采摘
2个苹果
*****我采摘
3个苹果
$$$$$我采摘
3个苹果
$$$$$我采摘
4个苹果
*****我采摘
4个苹果
*****我采摘
5个苹果
$$$$$我采摘
5个苹果
(4)守护线程
守护线程就是主线程不管该线程的执行情况,只要其它子线程结束以及主线程执行结束,程序直接结束,守护线程也直接结束
import threading
import time
def task1(a
):
print(threading
.current_thread
().name
,2,a
)
for i
in range(1,6):
time
.sleep
(2)
print("*****我采摘%s个苹果"%i
)
def task2():
print(threading
.current_thread
().name
, 3)
for i
in range(1,6):
time
.sleep
(2)
print("$$$$$我采摘%s个苹果"%i
)
print(threading
.current_thread
().name
,0)
print(time
.ctime
())
per1
=threading
.Thread
(target
=task1
,name
="线程1",args
=(10,))
per2
=threading
.Thread
(target
=task2
)
per2
.setName
("线程2")
per1
.setDaemon
(True)
per2
.setDaemon
(True)
per1
.start
()
per2
.start
()
print(time
.ctime
())
print(threading
.current_thread
().name
,1)
MainThread
0
Sat Jul
4 13:02:58 2020
线程
1 2 10
线程2Sat Jul
4 13:02:58 2020
MainThread
1
4.锁线程实例
(1)不加锁
import threading
blance
= 0
def access(n
):
global blance
blance
= blance
+ n
blance
= blance
- n
def task(arg
, n
):
while arg
> 0:
try:
access
(n
)
finally:
arg
= arg
- 1
t1
= threading
.Thread
(target
=task
, args
=(40000, 5))
t2
= threading
.Thread
(target
=task
, args
=(40000, 8))
t1
.start
()
t2
.start
()
t1
.join
()
t2
.join
()
print(blance
)
多次运行后,得出的结果分别为:0,0,0,5,0,0,-8,0,5,5,0由上可知,若多个线程不加锁,就有可能多个线程同时修改某一个变量,会将数据改乱,得出的结果会与实际结果不同
(2)加锁
通过 threading.RLock() 方法来创建锁,之后通过 acquire() 方法来获取锁,release() 方法释放锁
import threading
blance
= 0
lock
= threading
.RLock
()
def access(n
):
global blance
blance
= blance
+ n
blance
= blance
- n
def task(arg
, n
):
while arg
> 0:
lock
.acquire
()
try:
access
(n
)
finally:
lock
.release
()
arg
= arg
- 1
t1
= threading
.Thread
(target
=task
, args
=(40000, 5))
t2
= threading
.Thread
(target
=task
, args
=(40000, 8))
t1
.start
()
t2
.start
()
t1
.join
()
t2
.join
()
print(blance
)
无论程序执行多少次,结果都是0,与实际结果相同