python learning Process and Thread.py

# 多进程
# Windows下面没有fork ,请在linux下跑下面的代码
'''
import os

print('Process (%s) start...' % os.getpid())

pid = os.fork()
if pid==0:
    print('I am child process (%s) and my parent is %s' % (os.getpid(), os.getppid())
else:
    print('I (%s) just created a child process(%s).' % (os.getpid(), pid))
'''

# windows 下没有 fork,实现多进程要使用 multiprocessing 模块

from multiprocessing import Process
import os, time

def run_proc(name):
    print('Run child process %s (%s)...' % (name, os.getpid()))

if __name__=='__main__':
    print('Parent process %s.' % os.getpid())
    p = Process(target=run_proc, args=('test',)) # target 将函数作为单个进程,args 是传参数
    print('Child process will start.')
    p.start() # 启动
    p.join() # 等待子进程结束后继续运行
    print('Child process is end.')
    print('..................')
    time.sleep(1)


# Pool
# 要启动大量的子进程,可以用进程池的方式批量创建子进程:

from multiprocessing import Pool
import os, time, random

def long_time_task(name):
    print('Run task %s (%s)' % (name, os.getpid()))
    start = time.time() # 返回当前时间的时间戳
    time.sleep(random.random() * 3)  # random() 方法返回随机生成的一个实数,它在[0,1)范围内。
    end = time.time()
    print('Task %s runs %0.2f seconds' % (name, (end-start)))

if __name__ == '__main__':
    print('Parent process %s.'% os.getpid())
    p = Pool(3)
    for i in range(4):
        p.apply_async(long_time_task, args=(i,))
    print('waiting for all subprocesses done...')
    p.close()
    p.join()
    print('Done')
    print('..................')
    time.sleep(1)

# 对Pool对象调用join()方法会等待所有子进程执行完毕,调用join()之前必须先调用close(),调用close()之后就不能继续添加新的Process了。



# 进程间通信

# Python的multiprocessing模块包装了底层的机制,提供了Queue、Pipes等多种方式来交换数据。

# 参考链接:https://www.cnblogs.com/kaituorensheng/p/4445418.html#_label5

from multiprocessing import Process, Queue
import os, time, random

# 写数据进程执行的代码:
def write(q):
    print('Process to write: %s' % os.getpid())
    for value in ['a','b','c']:
        print('Put %s to queue...' % value)
        q.put(value)
        time.sleep(random.random())

# 读
def read(q):
    print('Process to read: %s' % os.getpid())
    while True:
        value = q.get(True)
        print('Gets %s from queue.' % value)

if __name__ == '__main__':
    # 父进程创建队列,传递给各个子进程
    q = Queue()
    pw = Process(target=write, args=(q,))
    pr = Process(target=read, args=(q,))

    pw.start()
    pr.start()
    pw.join()
    pr.terminate() # pr进程里是死循环,无法等待其结束,只能强行终止:
    print('Done')
    print('..................')
    time.sleep(1)


##############################################################

# 多线程

'''
多任务可以由多进程完成,也可以由一个进程内的多线程完成。

我们前面提到了进程是由若干线程组成的,一个进程至少有一个线程。

由于线程是操作系统直接支持的执行单元,因此,高级语言通常都内置多线程的支持,Python也不例外,并且,Python的线程是真正的Posix Thread,而不是模拟出来的线程。
'''

# Python的标准库中,绝大多数情况下,我们只需要使用threading这个高级模块。

# 启动一个线程就是把一个函数传入并创建Thread实例,然后调用start()开始执行:

import time, threading

# 新进程执行的代码:

def loop():
    print('thread %s is running ...' % threading.current_thread().name)
    n = 0
    while n < 3:
        n = n + 1
        print('thread %s >>> %s' % (threading.current_thread().name,n))
        time.sleep(1)
    print('thread %s ended.' % threading.current_thread().name)

print('thread %s is running ...' % threading.current_thread().name)
t = threading.Thread(target=loop, name='LoopTread') # 子线程的名字在创建时指定,我们用LoopThread命名子线程。名字仅仅在打印时用来显示,完全没有其他意义
t.start()
t.join()
print('thread %s ended.' % threading.current_thread().name)

# 任何进程默认就会启动一个线程,我们把该线程称为主线程,主线程又可以启动新的线程
# current_thread()函数,它永远返回当前线程的实例。


# Lock

# 多线程和多进程最大的不同在于,多进程中,同一个变量,各自有一份拷贝存在于每个进程中,互不影响,
# 而多线程中,所有变量都由所有线程共享,所以,任何一个变量都可以被任何一个线程修改,因此,线程之间共享数据最大的危险在于多个线程同时改一个变量,把内容给改乱了。


# 假定这是你的银行存款:
balance = 0

def change_it(n):
    # 先存后取,结果应该为0:
    global balance # 告诉Python这个变量名不是局部的,而是 全局 的
    ###
    balance = balance + n
    balance = balance - n
    ### 这两句语句在一个线程里应该是要连续执行才对

def run_thread(n):
    for i in range(5000000):
        change_it(n)

t1 = threading.Thread(target=run_thread,args=(5,))
t2 = threading.Thread(target=run_thread,args=(8,))
t1.start()
t2.start()
t1.join()
t2.join()
print(balance) # 由于线程的调度是由操作系统决定的,当t1、t2交替执行时,只要循环次数足够多,balance的结果就不一定是0了。
print('Done.......................')


# 为函数 change_it 添加一个锁
# 当某个线程开始执行change_it()时,该线程因为获得了锁,因此其他线程不能同时执行change_it(),只能等待,直到锁被释放后,获得该锁以后才能执行。

balance = 0
lock = threading.Lock()

def run_thread(n):
    for i in range(5000000):
        # p(信号量)
        lock.acquire()
        try:
            change_it(n)
        finally:
            # v(信号量)
            lock.release()

print(balance)
print('Done.......................')

猜你喜欢

转载自www.cnblogs.com/ZCplayground/p/9026428.html