线程相关内容

1.线程: 是cpu执行程序的最小单元,一份进程中可以包含多个线程,开辟线程时无需重新分配资源,子线程跟主线程共享资源。

from multiprocessing import Process
from threading import Thread
import time
# 进程并发
def func(i):
    print(i)

if __name__ == "__main__":
    lst = []
    time1 = time.time()
    for i in range(100):
        p = Process(target=func,args=(i,))
        p.start()
        lst.append(p)
    for j in lst:
        j.join()
    time2 = time.time()
    print(time2-time1) # 2.086568593978882



from multiprocessing import Process
from threading import Thread
import time
# 线程并发
def func(i):
    print(i)

if __name__ == "__main__":
    lst = []
    time1 = time.time()
    for i in range(100):
        t = Thread(target=func,args=(i,))
        t.start()
        lst.append(t)
    for j in lst:
        j.join() # 线程也是异步的
    time2 = time.time()
    print(time2-time1) # 0.01492619514465332  因无需再分配资源,所以线程速度大大快于进程

1.1  线程之间共享数据

from threading import Thread
a = 100
def func():
    global a
    a -= 1
if __name__ == "__main__":
    for i in range(10):
        t = Thread(target=func)
        t.start()
    print(a) # 90

1.2  用类定义线程

from threading import Thread
class Mythread(Thread):
    def __init__(self,args):
        self.args = args
        super().__init__() # 若有参数则要通过super()调父类里面的init方法
    def run(self): # 必须命名为run()方法
        print("用类定义的线程",self.args)

if __name__ == "__main__":
    t = Mythread(888)
    t.start() # 用类定义的线程 888

1.3  线程相关的函数

from threading import Thread
import time
def func():
    time.sleep(1)
    print(111)

# (1) is_alive(): 判断线程是否还存在
if __name__ == "__main__":
    t = Thread(target=func)
    t.start()
    res = t.is_alive()
    print(res) # True


# (2) setName():设置线程的名字
if __name__ == "__main__":
    t = Thread(target=func)
    t.start()
    t.setName("8号")
    print(t) # <Thread(8号, started 5880)>


# (3) getName(): 获取线程名字
if __name__ == "__main__":
    t = Thread(target=func)
    t.start()
    t.setName("8号")
    print(t.getName()) # 8号


# (4) currentThread().ident:查看线程id号
from threading import currentThread #需要引入currentThread
if __name__ == "__main__":
    t = Thread(target=func)
    t.start()
    res = currentThread().ident
    print(res) # 3380


# (5) enumerate():返回正在运行的线程列表
from threading import enumerate
if __name__ == "__main__":
    t = Thread(target=func)
    t.start()
    lst = enumerate()
    print(lst) # [<_MainThread(MainThread, started 9096)>, <Thread(Thread-1, started 14956)>]


# (6) activeCount():返回正在运行的线程数量
from threading import enumerate,activeCount
if __name__ == "__main__":
    t = Thread(target=func)
    t.start()
    res = activeCount() # 方式一
    print(res) # 2
    lst = enumerate() # 方式二
    print(len(lst)) # 2

1.4 守护线程:守护的是所有的子线程,等所有子线程都执行完后,守护线程也会被终止

from threading import Thread
import time
def func1():
    time.sleep(0.5)
    print("老二,你结束没?")
    time.sleep(0.5)
    print("我要关掉了")

def func2():
    time.sleep(1.5)
    print("大哥,等我一会")
    time.sleep(1)

if __name__ == "__main__":
    t1 = Thread(target=func1)
    t1.setDaemon(True)
    t1.start()
    t2 = Thread(target=func2)
    t2.start()
    t2.join()
    print("臭小子,还有你们的老父亲我呢")
    time.sleep(1)
    print("OK,回家")
# 在主线程和func2都结束后,func1结束,程序结束

1.5 Lock:上锁,保护数据安全

from threading import Thread,Lock
import time
money = 1000000
def func(lock):
    global money
    with lock:
        for i in range(100000):
            money -= 1

if __name__ == "__main__":
    lock = Lock()
    lst = []
    for i in range(10):
        t = Thread(target=func,args=(lock,))
        t.start()
        lst.append(t)
    print("败家子儿,我的一百万,被你们折腾得就剩{}了".format(money))
    for j in lst:
        j.join()
    print("败家子儿,我的一百万,被你们折腾得就剩{}了".format(money))
    print("还不赶紧还给我")

def func(lock):
    global money
    with lock:
        for i in range(100000):
            money += 1

if __name__ == "__main__":
    lock = Lock()
    lst = []
    for i in range(10):
        t = Thread(target=func,args=(lock,))
        t.start()
        lst.append(t)
    print("还给你,有啥了不起,给你{}".format(money))
    for j in lst:
        j.join()
    print("对,都还给你,{}元".format(money))

1.6 信号量Semaphore: 线程中控制锁的数量

from threading import Thread,Semaphore
import time
def func(sem,i):
    sem.acquire()
    print("这是"+str(i))
    time.sleep(1)
    sem.release()

if __name__ == "__main__":
    sem = Semaphore(3)
    for i in range(10):
        t = Thread(target=func,args=(sem,i))
        t.start()


# with语法
from threading import Thread,Semaphore
import time
def func(i):

    with sem:
        print("给我食物,给我钱")
        print(i)
        time.sleep(2)

if __name__ == "__main__":
    sem = Semaphore(2)
    lst1 = []
    lst = ["肉包子", "200万", "排骨汤", "腊肠", "腊鱼", "花生米", "酸菜鱼", "100万"]
    for i in lst:
        t = Thread(target=func,args=(i,))
        t.start()
        lst1.append(t)
    for j in lst1:
        j.join()

1.7: 线程的缺陷

python中的线程可以并发,但是不能并行(同一个进程下的多个线程不能分开被多个cpu同时执行)
原因:
全局解释器锁(Cpython解释器特有) GIL锁:同一时间,一个进程下的多个线程只能被一个cpu执行
python是解释型语言,执行一句编译一句,而不是一次性全部编译成功,不能提前规划,都是临时调度
容易造成cpu执行调度异常.所以加了一把锁叫GIL

想要并行的解决办法:
(1)用多进程间接实现线程的并行
(2)换一个Pypy,Jpython解释器

程序分为计算密集型和io密集型
对于计算密集型程序会过度依赖cpu,但网页,爬虫,OA办公,这种io密集型的程序里,python绰绰有余

原文地址:https://www.cnblogs.com/fdsimin/p/13094002.html