04线程

一、线程的引入
如果说在操作系统中引入进程的目的是使多个程序并发执行,以改善资源利用率及提高系统吞吐量,那么在操作系统中再引入线程则是为了
减少程序并发执行所付出的时空开销,使操作系统具有更好的并发性。
进程的两个基本属性:
1、进城是一个拥有资源的独立单位
2、进程同时又是一个可以被处理器,单独调度和分配的单元
为了使进程能并发执行,操作系统还必须进行一系列的操作,如创建进程、撤销进程和进程切换,在进行这些操作时操作系统要为进程分配
资源及回收资源为运行进程保存现场信息,这些工作都需要付出较多的时空开销,
正因如此在系统中不易设置过多的进程,进程的切换频率也不宜太高,从而限制了系统并发程度。
为了使多个程序更好的并发执行并尽量减少操作系统的开销,操作系统将进行了两个属性分离开来,分别有不同的实体来实现,
让线程去完成第2个基本属性,而进程只完成第1个基本属性的任务。
二、创建线程的两种方式
(1)方法一
from threading import Thread
import time, random
def fun(name):
    print('{} is starting,'.format(name))
    time.sleep(random.randint(1,3))
    print('{} is done'.format(name))


if __name__ == '__main__':
    t = Thread(target=fun, args=('cc', ))
    t.start()
    print('')
(2)方法二
class MyThread(Thread):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def run(self):
        print('{} is starting,'.format(self.name))
        time.sleep(random.randint(1, 3))
        print('{} is done'.format(self.name))

if __name__ == '__main__':
    t = MyThread('cc')
    t.start()
    print('')

 例1、多线程实现并发的套接字通信

# 服务器端
from threading import Thread, current_thread
from socket import *
from time import ctime

def communicate(conn):
    print('子线程,',current_thread().getName())
    while True:
        try:
            data = conn.recv(1024)
            if not data: break
            print('recv:', data.decode('utf-8'))
            conn.send(('[{}] {}'.format(ctime(), data)).encode('utf-8'))
        except Exception:
            break
    conn.close()


def server(ip,port):
    print('主线程,', current_thread().getName())
    tcpSerSock = socket(AF_INET, SOCK_STREAM)
    tcpSerSock.bind((ip, port))
    tcpSerSock.listen(5)

    while True:
        print('waiting for connecting....')
        conn, addr = tcpSerSock.accept()
        print('connecting from :', addr)

        # communicate(conn)
        t = Thread(target=communicate, args=(conn, ))#利用多线程解决并发问题
        t.start()

    tcpSerSock.close()


if __name__ == '__main__':
    server('127.0.0.1', 3000)
# 客户端
from socket import *
from time import ctime

tcpCliSock = socket(AF_INET, SOCK_STREAM)
tcpCliSock.connect(('127.0.0.1', 3000))

while True:
    data = input('please input:')
    if not data:
        continue
    tcpCliSock.send(data.encode('utf-8'))
    data = tcpCliSock.recv(1024)
    print('recv:',data.decode('utf-8'))

tcpCliSock.close()

 例2、三个任务,一个接收用户输入,一个将用户输入的内容格式化成大写,一个将格式化后的结果存入文件

from threading import Thread

msg_l = []
format_l = []
def recv_input():
    while True:
        msg = input('please input:')
        if not msg:continue
        msg_l.append(msg)

def str_to_upper():
    while True:
        if msg_l:
            res = msg_l.pop()
            format_l.append(res.upper())

def save():
    while True:
        if format_l:
            with open('data.txt', 'a') as f:
                res = format_l.pop()
                f.write(res+'\n')

if __name__ == '__main__':
    t1 = Thread(target=recv_input)
    t2 = Thread(target=str_to_upper)
    t3 = Thread(target=save)
    t1.start()
    t2.start()
    t3.start()
三、守护线程:等待所有的非守护线程结束后它才结束
from threading import Thread
import time

def fun1():
    print('123 start...')
    time.sleep(3)
    print('123 end...')


def fun2():
    print('456 start...')
    time.sleep(1)
    print('456 end...')


if __name__ == '__main__':
    t1 = Thread(target=fun1)
    t2 = Thread(target=fun2)
    t1.daemon = True
    t1.start()
    t2.start()
    print('主线程。。。')
四、线程相关的其他方法
Thread实例对象的方法
isAlive(): 返回线程是否活动的。
getName(): 返回线程名。
setName(): 设置线程名。

threading模块提供的一些方法:
threading.currentThread(): 返回当前的线程变量。
threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。











 
posted @ 2021-03-01 14:52  cheng4632  阅读(64)  评论(0编辑  收藏  举报