线程

 一. 线程

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,
是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中
,进程是线程的容器。程序是指令、数据及其组织形式的描述,
进程是程序的实体。

线程: 是程序中一个单一的顺序控制流程。进程内有一个相对独立的、
可调度的执行单元,是系统独立调度和分派CPU的基本单位指令运行
时的程序的调度单位。
在单个程序中同时运行多个线程完成不同的工作,称为多线程。

进程一般有三个状态:就绪状态、执行状态和等待状态【或称阻塞状态】;
进程只能由父进程建立,系统中所有的进程形成一种进程树的层次体系;
挂起命令可由进程自己和其他进程发出,但是解除挂起命令只能由其他进程发出。

进程一般有三个状态:就绪状态、执行状态和等待状态【或称阻塞状态】
;进程只能由父进程建立,系统中所有的进程形成一种进程树的层次体系
;挂起命令可由进程自己和其他进程发出,但是解除挂起命令只能由其他进程发出。

 

在一个进程内部 要同时干多件事 就需要同时运行多个子任务
我们把进程内的这些子任务叫线程

线程通常叫做轻型的进程 线程是共享内存空间的 并发执行的多任务,每一个线程
都共享一个进程的资源

线程是最小的执行单元 而进程由至少一个线程组成 如何调度进程和线程
完全有操作系统绝对 程序自己不能决定什么时候执行 执行多长的时间

模块:

1._thraed 模块 低级模块(意思接近底层c语言)

2.threading 模块 高级模块 对_thraed进行了

启动一个线程

import threading,time

def run():
    print("子线程(%s)开始"%(threading.current_thread().name))
    # 实现线程功能
    print("打印了")
    time.sleep(2)
    print("子线程(%s)结束"%(threading.current_thread().name))

if __name__ == '__main__':

# 任何进程默认就会启动一个线程 称为主线程 主线程可以器动新的子线程
# current_thread()   #返回当前线程的实例  在哪个线程里面就返回哪个线程的实例

    print("主线程(%s)启动"%(threading.current_thread().name)) # 打印当前线程名称


    # 01创建子线程              
     # target=run执行指定代码
     # name    是指线程名称
    t=threading.Thread(target=run,name="rooTHread")

    # 线程执行
    t.start()
    print("主线程(%s)结束"%(threading.current_thread().name)) # 打印当前线程名称

主线程(MainThread)启动
子线程(rooTHread)开始
主线程(MainThread)结束
打印了
子线程(rooTHread)结束

启动一个线程 

import threading,time

aa=100000000000000000000000

def run():
    print("子线程(%s)开始"%(threading.current_thread().name))
    # 实现线程功能
    print("打印了")
    time.sleep(2)
    print(aa)
    print("子线程(%s)结束"%(threading.current_thread().name))


if __name__ == '__main__':

# 任何进程默认就会启动一个线程 称为主线程 主线程可以器动新的子线程
# current_thread()   #返回当前线程的实例  在哪个线程里面就返回哪个线程的实例
    print("主线程(%s)启动"%(threading.current_thread().name)) # 打印当前线程名称
    # 01创建子线程              
    # target=run执行指定代码
    # name    是指线程名称
    t=threading.Thread(target=run,name="rooTHread")


    # 线程执行
    t.start()
# 等待线程结束
    t.join()
    print("主线程(%s)结束"%(threading.current_thread().name)) # 打印当前线程名称



# 主线程(MainThread)启动
# 子线程(rooTHread)开始
# 打印了
# 100000000000000000000000
# 子线程(rooTHread)结束
# 主线程(MainThread)结束

启动一个线程传值

import threading,time

aa=100000000000000000000000
def run(num):

    print("子线程(%s)开始"%(threading.current_thread().name))

    # 实现线程功能
    print("打印了",num)
    time.sleep(2)
    print(aa)

    print("子线程(%s)结束"%(threading.current_thread().name))

if __name__ == '__main__':

# 任何进程默认就会启动一个线程 称为主线程 主线程可以器动新的子线程
# current_thread()   #返回当前线程的实例  在哪个线程里面就返回哪个线程的实例
    print("主线程(%s)启动"%(threading.current_thread().name)) # 打印当前线程名称

    # 01创建子线程              
    # target=run执行指定代码
    # name    是指线程名称
    t=threading.Thread(target=run,name="rooTHread",args=(1111110000,))
    # 线程执行
    t.start()
    # 等待线程结束
    t.join()
    print("主线程(%s)结束"%(threading.current_thread().name)) # 打印当前线程名称

# 主线程(MainThread)启动
# 子线程(rooTHread)开始
# 打印了 1111110000
# 100000000000000000000000
# 子线程(rooTHread)结束
# 主线程(MainThread)结束

线程间是共享数据但是数据会乱

import threading,time

"""多线程和多进程最大的不同在于 多进程中 
同一个变量 各自有一份拷贝存在每个进程中
互相不影响 而多线程 所有变量都有所有线程共享 所以任何一个变量都可以被任意
一个线程修改 因此 线程之间共享数据最大的危险在于多个线程同时修改一个变量
容易吧内容改乱
"""
aa=0

def run(n):
  for i in range(1000000):
  
    global aa
    aa=aa+n     #15=9+5
    aa=aa-n      #9
if __name__ == '__main__':
     t1=threading.Thread(target=run,args=(6,))
     t2=threading.Thread(target=run,args=(9,))
     t1.start()
     t2.start()
     t1.join()
     t2.join()

     print("aa:",aa)

# 线程1  aa=aa+6         # aa-6=3
# 线程2  aa=aa+9
           # 3-9=-6

 使用线程锁解决数据混乱

"""
两个线程同时工作 一个存钱 一个取钱

可能导致数据异常

思路:加锁     能解决数据乱的问题
"""
import threading,time
# 锁对象
lock=threading.Lock()
aa=0
def run(n):
  for i in range(1000000):
  
    global aa
    # 加锁   
    # 确保了这段代码只能由一个线程从头到尾的完整性   从而保持了数据不会乱
    # 加锁因为阻止了多线程的并发 包含锁的某段代码实际上只能以单线程模式执行
    # 从而效率降低了  要比单线程快点
    # 由于他可以存在多个锁   不同线程持有不同的锁 有可能试图获取其它的锁
    # 可能造成死锁  导致多个线程挂起 只能靠操作系统了强制终止

    lock.acquire()
    try:
      aa=aa+n     #15=9+5
      aa=aa-n      #9
    finally:
      # 修改完一定要释放锁
      lock.release()
if __name__ == '__main__':
     t1=threading.Thread(target=run,args=(6,))
     t2=threading.Thread(target=run,args=(9,))
     t1.start()
     t2.start()
     t1.join()
     t2.join()
     print("aa:",aa)

"""# 与上面的代码功能相同  with look 可以自动上锁 解锁  
# 只是这样可以降低死锁的概率
     with lock:
        aa=aa+n 
        aa=aa-n 
"""

 threadlocal

import threading

num=0
"""创建一个全局的thraedlocal
每个线程有独有的存储空间
每个线程threading对象都可以读写 但是互不影响"""
local=threading.local()

def run(x,n):
    # 每个线程都有local.x 就是线程的局部变量
    x=x+n
    x=x-n


def func(n):
    local.x=num
    for i in range(100000):
          run(local.x,n)
    print(threading.current_thread().name,local.x) 
if __name__ == '__main__':

     t1=threading.Thread(target=func,args=(6,))
     t2=threading.Thread(target=func,args=(9,))
     t1.start()
     t2.start()
     t1.join()
     t2.join()
     print("aa:",num)

"""Thread-1 0
Thread-2 0
aa: 0
"""
"""
作用 :为每一个线程绑定一个数据库连接   或者http请求  这样一个线程的所有
       调用到的处理函数都可以非常方便访问这些资源
  """

 

 信号量控制线程数量

import threading,time

sem=threading.Semaphore(3)  # 控制线程的数量    意思三个三个线程走
def run():

 with sem:
   for i in range(10):
      print(threading.current_thread().name,i)
      time.sleep(2)

if __name__=="__main__":

    for i in range(5):
         threading.Thread(target=run).start()

 凑够一定数量才能一起执行

import threading,time

bar=threading.Barrier(4)    # 凑够四个线程才往下执行

def run():

      print("开始",threading.current_thread().name)
      time.sleep(2)
      bar.wait()

      print("结束",threading.current_thread().name)

if __name__=="__main__":

    for i in range(5):
         threading.Thread(target=run).start()


# 开始 Thread-1
# 开始 Thread-2
# 开始 Thread-3
# 开始 Thread-4
# 开始 Thread-5
# 结束 Thread-2
# 结束 Thread-1
# 结束 Thread-4
# 结束 Thread-3
# 结束 Thread-5

 

 定时线程

import threading,time


def run():
      print("开始444444444")

t=threading.Timer(5,run)
t.start()
t.join()

print("延时执行结束")

 线程通讯

import threading,time
def func():

     # 事件对象
    event=threading.Event()
    def run():
        for i in range(5):
           # 阻塞等待事件的触发
        
            event.wait()
            # 重置
            event.clear()
            print("哈哈哈哈哈哈哈哈或")
    t=threading.Thread(target=run).start()
    return event
e=func()

# 触发事件
for i in range(5):
   time.sleep(2)
   e.set()

 生产者和消费者

import threading,time,queue,random
"""
生产者  : 生产数据   

消费者 : 处理数据
"""

# 生产者
def product(id,q):
  while True:
    num=random.randint(0,100)
    q.put(num)
    print("生产者生产了数据放入了队列",id,num)
    time.sleep(5)
# 任务完成
  q.task_dome()

# 消费者
def customer(id,q):

  while True:
     item=q.get()
     if item is None:
       break
     print("消费者消费数据",id,item)
     time.sleep(5)
  # 完成任务
  q.task_dome()

if __name__=="__main__":

   # 消息列队
   q=queue.Queue()


   # 启动生产者
   for i in range(4):
     threading.Thread(target=product,args=(i,q)).start()

   # 启动消费者
   for i in range(3):
     threading.Thread(target=customer,args=(i,q)).start()

生产者生产了数据放入了队列 0 92
生产者生产了数据放入了队列 1 3
生产者生产了数据放入了队列 2 51
生产者生产了数据放入了队列 3 54
消费者消费数据 0 92
消费者消费数据 1 3
消费者消费数据 2 51
生产者生产了数据放入了队列 0 98
生产者生产了数据放入了队列 2 83
生产者生产了数据放入了队列 1 40
生产者生产了数据放入了队列 3 7
消费者消费数据 0 54
消费者消费数据 1 98
消费者消费数据 2 83
生产者生产了数据放入了队列 0 73
生产者生产了数据放入了队列 2 53
生产者生产了数据放入了队列 1 51
生产者生产了数据放入了队列 3 20
消费者消费数据 0 40
消费者消费数据 1 7
消费者消费数据 2 73

 二. 进程案例

1. 线程客服端与服务器端的交互

client客服端.py

import socket
client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(("192.168.100.111",8082))
while True:
   
    data=input("请输入给服务器的数据")
    client.send(data.encode("utf-8"))
    info=client.recv(1024)
    print(info.decode("utf-8"))

client客服端1.py

import socket
client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

client.connect(("192.168.100.111",8082))

count=0
while True:
    count+=1
    data=input("请输入给服务器的数据")
    client.send(data.encode("utf-8"))
    info=client.recv(1024)
    print(info.decode("utf-8"))

server服务器.py

import socket
import threading

# 01创建服务器socket
server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)


# 02绑定端口和ip
server.bind(('192.168.100.111',8082))

# 03监听
server.listen(5)

print("启动成功了.................")

def run(ck):

    data=clientSocket.recv(1024)
    print("客服端说:"+data.decode("utf-8"))
    # sendData=input("输入返回给客服端的信息:")
    clientSocket.send("大美女来了哈哈哈哈哈".encode("utf-8"))

print("服务接受成功了哈哈哈哈")

while True:

    # 04等待连接
    clientSocket,clientAddress=server.accept()
    # print(str(clientSocket),clientAddress,"哈哈哈哈哈哈哈哈去")

    t=threading.Thread(target=run,args=(clientSocket,))

    t.start()


 

2. 线程客服端与服务器端的交互聊天

client客服端.py

import socket
client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

client.connect(("192.168.100.111",8082))

while True:
   
    data=input("请输入给服务器的数据")
    client.send(data.encode("utf-8"))
    info=client.recv(1024)
    print(info.decode("utf-8"))

client客服端1.py

import socket

client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

client.connect(("192.168.100.111",8082))

count=0

while True:
    count+=1
    data=input("请输入给服务器的数据")
    client.send(data.encode("utf-8"))
    info=client.recv(1024)
    print(info.decode("utf-8"))

server服务器.py

import socket
import threading

# 01创建服务器socket
server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

# 02绑定端口和ip
server.bind(('192.168.100.111',8082))

# 03监听
server.listen(5)

print("启动成功了.................")
def run(ck):

    data=clientSocket.recv(1024)
    print("客服端说:"+data.decode("utf-8"))
    # sendData=input("输入返回给客服端的信息:")
    clientSocket.send("大美女来了哈哈哈哈哈".encode("utf-8"))

print("服务接受成功了哈哈哈哈")

while True:

    # 04等待连接
    clientSocket,clientAddress=server.accept()
    # print(str(clientSocket),clientAddress,"哈哈哈哈哈哈哈哈去")

    t=threading.Thread(target=run,args=(clientSocket,))
    t.start()


 

 

posted @ 2019-01-14 14:33  Loversuperme  阅读(104)  评论(0编辑  收藏  举报