python学习——进程

1. 操作系统/应用程序

a. 硬件
- 硬盘
- CPU
- 主板
- 显卡
- 内存
- 电源
...
b. 装系统(软件)
- 系统就是一个由程序员写出来软件,该软件用于控制计算机的硬件,
让他们之间进行相互配合。

c. 安软件(安装应用程序)
- QQ
- 百度云
- pycharm
...

2. 并发和并行
并发,伪,由于一个人执行速度特别快,人感觉不到停顿。
并行,真,创建10个人同时操作。

3. 线程、进程
a. 单进程、单线程的应用程序

print('666')

b. 到底什么是线程?什么是进程?
Python自己没有这玩意,Python中调用的操作系统的线程和进程。

c. 单进程、多线程的应用程序
代码:
import threading
print('666')

def func(arg):
print(arg)
t = threading.Thread(target=func)
t.start()

print('end')

一个应用程序(软件),可以有多个进程(默认只有一个),一个进程中可以创建多个线程(默认一个)。

d. 故事: Alex甄嬛西游传

总结:

1. 操作系统帮助开发者操作硬件。
2. 程序员写好代码在操作系统上运行(依赖解释器)。

任务特别多的情况:
3. 以前的你,写代码:
import threading
import requests
import uuid

url_list = [
'https://www3.autoimg.cn/newsdfs/g28/M05/F9/98/120x90_0_autohomecar__ChsEnluQmUmARAhAAAFES6mpmTM281.jpg',
'https://www2.autoimg.cn/newsdfs/g28/M09/FC/06/120x90_0_autohomecar__ChcCR1uQlD6AT4P3AAGRMJX7834274.jpg',
'https://www2.autoimg.cn/newsdfs/g3/M00/C6/A9/120x90_0_autohomecar__ChsEkVuPsdqAQz3zAAEYvWuAspI061.jpg',
]

def task(url):
""""""

"""
1. DNS解析,根据域名解析出IP
2. 创建socket客户端 sk = socket.socket()
3. 向服务端发起连接请求 sk.connect()
4. 发送数据(我要图片) sk.send(...)
5. 接收数据 sk.recv(8096)

接收到数据后写入文件。
"""
ret = requests.get(url)
file_name = str(uuid.uuid4()) + '.jpg'
with open(file_name, mode='wb') as f:
f.write(ret.content)

for url in url_list:
task()


"""
- 你写好代码
- 交给解释器运行: python s1.py
- 解释器读取代码,再交给操作系统去执行,根据你的代码去选择创建多少个线程/进程去执行(单进程/单线程)。
- 操作系统调用硬件:硬盘、cpu、网卡....
"""

4. 现在的你,写代码:
import threading
import requests
import uuid

url_list = [
'https://www3.autoimg.cn/newsdfs/g28/M05/F9/98/120x90_0_autohomecar__ChsEnluQmUmARAhAAAFES6mpmTM281.jpg',
'https://www2.autoimg.cn/newsdfs/g28/M09/FC/06/120x90_0_autohomecar__ChcCR1uQlD6AT4P3AAGRMJX7834274.jpg',
'https://www2.autoimg.cn/newsdfs/g3/M00/C6/A9/120x90_0_autohomecar__ChsEkVuPsdqAQz3zAAEYvWuAspI061.jpg',
]

def task(url):
""""""

"""
1. DNS解析,根据域名解析出IP
2. 创建socket客户端 sk = socket.socket()
3. 向服务端发起连接请求 sk.connect()
4. 发送数据(我要图片) sk.send(...)
5. 接收数据 sk.recv(8096)

接收到数据后写入文件。
"""
ret = requests.get(url)
file_name = str(uuid.uuid4()) + '.jpg'
with open(file_name, mode='wb') as f:
f.write(ret.content)

for url in url_list:

t = threading.Thread(target=task,args=(url,))
t.start()


"""
- 你写好代码
- 交给解释器运行: python s2.py
- 解释器读取代码,再交给操作系统去执行,根据你的代码去选择创建多少个线程/进程去执行(单进程/4线程)。
- 操作系统调用硬件:硬盘、cpu、网卡....
"""

Python多线程情况下:
- 计算密集型操作:效率低。(GIL锁)
- IO操作: 效率高

Python多进程的情况下:
- 计算密集型操作:效率高(浪费资源)。 不得已而为之。
- IO操作: 效率高 (浪费资源)。

以后写Python时:
IO密集型用多线程: 文件/输入输出/socket网络通信
计算密集型用多进程。

扩展:
Java多线程情况下:
- 计算密集型操作:效率高。
- IO操作: 效率高
Python多进程的情况下:
- 计算密集型操作:效率高(浪费资源)。
- IO操作: 效率高 浪费资源)。

4. Python中线程和进程(GIL锁)
GIL锁,全局解释器锁。用于限制一个进程中同一时刻只有一个线程被cpu调度。

扩展:默认GIL锁在执行100个cpu指令(过期时间)。

5. Python线程编写
  线程的使用
  ###################### 1.线程的基本使用 #################
  
import threading

def func(arg):
    print(arg)

t = threading.Thread(target=func,args=(11,))
t.start()

print(123)
  ###################### 2.主线程默认等子线程执行完毕 #################
import threading
import time
def func(arg):
    time.sleep(arg)
    print(arg)

t1 = threading.Thread(target=func,args=(3,))
t1.start()

t2 = threading.Thread(target=func,args=(9,))
t2.start()

print(123)
  ###################### 3.主线程不再等,主线程终止则所有子线程终止 #################
import threading
import time
def func(arg):
    time.sleep(2)
    print(arg)

t1 = threading.Thread(target=func,args=(3,))
t1.setDaemon(True)#守护线程,开启优先级很低,主线程运行完之后直接关闭守护线程
t1.start()

t2 = threading.Thread(target=func,args=(9,))
t2.setDaemon(True)#守护线程
t2.start()

print(123)
  ###################### 4.开发者可以控制主线程等待子线程(最多等待时间) #################
import threading
import time
def func(arg): time.sleep(0.01) print(arg) print('创建子线程t1') t1 = threading.Thread(target=func,args=(3,)) t1.start() # 无参数,让主线程在这里等着,等到子线程t1执行完毕,才可以继续往下走。 # 有参数,让主线程在这里最多等待n秒,无论是否执行完毕,会继续往下走。 t1.join(2) print('创建子线程t2') t2 = threading.Thread(target=func,args=(9,)) t2.start() t2.join(2) # 让主线程在这里等着,等到子线程t2执行完毕,才可以继续往下走。 print(123)
  ###################### 5.线程名称 #################
import threading
def func(arg):
    # 获取当前执行该函数的线程的对象
    t = threading.current_thread()
    # 根据当前线程对象获取当前线程名称
    name = t.getName()
    print(name,arg)

t1 = threading.Thread(target=func,args=(11,))
t1.setName('侯明魏')
t1.start()

t2 = threading.Thread(target=func,args=(22,))
t2.setName('刘宁钱')
t2.start()

print(123)
  ###################### 6.线程本质 #################
  # 先打印:11?123?
import threading
def func(arg):
    print(arg)

t1 = threading.Thread(target=func,args=(11,))
t1.start()
# start 是开始运行线程吗?不是
# start 告诉cpu,我已经准备就绪,你可以调度我了。
print(123)
  ###################### 7.补充:面向对象版本的多线程 #################
  # 多线程方式:1 (常见)
import threading
def func(arg):
    print(arg)

t1 = threading.Thread(target=func,args=(11,))
t1.start()
  # 多线程方式:2
import threading
class MyThread(threading.Thread):

    def run(self):
        print(11111,self._args,self._kwargs)

t1 = MyThread(args=(11,))
t1.start()

t2 = MyThread(args=(22,))
t2.start()

print('end')
  多线程
# #################### 1. 计算密集型多线程无用 ####################
import threading

v1 = [11,22,33] # +1
v2 = [44,55,66] # 100


def func(data,plus):
    for i in range(len(data)):
        data[i] = data[i] + plus

t1 = threading.Thread(target=func,args=(v1,1))
t1.start()

t2 = threading.Thread(target=func,args=(v2,100))
t2.start()
   # #################### 2. IO操作 多线程有用 ####################
import threading
import requests
import uuid

url_list = [
    'https://www3.autoimg.cn/newsdfs/g28/M05/F9/98/120x90_0_autohomecar__ChsEnluQmUmARAhAAAFES6mpmTM281.jpg',
    'https://www2.autoimg.cn/newsdfs/g28/M09/FC/06/120x90_0_autohomecar__ChcCR1uQlD6AT4P3AAGRMJX7834274.jpg',
    'https://www2.autoimg.cn/newsdfs/g3/M00/C6/A9/120x90_0_autohomecar__ChsEkVuPsdqAQz3zAAEYvWuAspI061.jpg',
]

def task(url):
    ret = requests.get(url)
    file_name = str(uuid.uuid4()) + '.jpg'
    with open(file_name, mode='wb') as f:
        f.write(ret.content)

for url in url_list:

    t = threading.Thread(target=task,args=(url,))
    t.start()
总结:
1. 应用程序/进程/线程的关系? *****(面试题:进程/线程/协程的区别?)

2. 为什么要创建线程?什么是线程
由于线程是cpu工作的最小单元,创建线程可以利用多核优势实现并行操作(Java/C#)。
注意:线程是为了工作。

3. 为什么要创建进程?什么是进程
进程和进程之间做数据隔离(Java/C#)。

注意:进程是为了提供环境让线程工作。隔离数据空间的单元

进程和线程的区别
  第一:进程是cpu资源分配的最小单元
     线程是cpu计算的最小单元
  第二:一个进程中可以有多个线程
  第三:对于python来说他的进程和线程与其他语言有差异,有GIL锁;GIL锁保证一个进程中同一时刻只有一个线程被cpu调度
  注意:IO密集型操作可以使用多线程;计算密集型可以使用多进程;
4. Python
a. Python中存在一个GIL锁。 *****
- 造成:多线程无法利用多核优势。
- 解决:开多进程处理(浪费资源)
总结:
IO密集型:多线程
计算密集型:多进程
b. 线程的创建
- Thread *****
- MyThread
c. 其他
- join *****等待子线程运行时间,超时则跳过此线程;无参数,让主线程在这里等着,等到子线程t1执行完毕,才可以继续往下走。有参数,让主线程在这里最多等待n秒,无论是否执行完毕,会继续往下走。
         - setDeanon      *****True是开启守护线程,优先级很低,主线程执行完毕后不会等待守护线程,程序直接关闭
- setName *****设置子线程名字
- threading.current_thread() *****当前线程
d. 锁
- 获得
- 释放

IO密集型:多线程
计算密集型:多进程
原文地址:https://www.cnblogs.com/bilx/p/11452922.html