进程线程简单了解

Posted 临风而眠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了进程线程简单了解相关的知识,希望对你有一定的参考价值。

线程进程简单了解

一.进程与线程

1.进程

​ 操作系统每次运行一个程序,都会给程序准备一块内存,该内存区域可以称为进程,进程是资源单位

​ 打开任务管理器,我们就可以看到很多进程

这时我们来运行输出一个经典的hello world

再次打开任务管理器,就会发现

​ 进程其实就是运行着的程序

2.线程

​ 线程是执行单位,一个进程里面至少要有一个线程

​ 线程由操作系统创建,每个线程对应一个代码执行的数据结构,保存了代码执行过程中的重要的状态信息(如当前代码执行到了哪个指令等等)

​ 上面那个hello world程序,虽然没有创建线程的代码,但当Python解释器运行起来(成为一个进程),OS就自动创建一个线程,常称为主线程,在这个主线程里面执行代码指令

启动一个程序默认会有一个主线程

def func():
    for i in range(1,1000):
        print("fuc",i,end=' ')

if __name__=='__main__':
    func()
    for i in range(1000,2001):
        print('main',i, end=' ')

​ 这就是一个单线程的程序

二.多线程

上面的程序输出1到2000,看似很快,几乎一秒就解决了

​ 那么如果要输出1到2000…00000000000000000000呢,如果只用一个线程,得等到猴年马月

​ (假设不需要按顺序输出)

而这时如果我们同时用100个线程,同时输出这2000......00000000000000000000个数字,那么理论上就可以减少100倍的执行时间

1.多线程写法一

将上面那个程序实现多线程

from threading import Thread  # 线程类
def func():
    for i in range(1, 1000):
        print(" fuc:", i, end=' ')
if __name__ == '__main__':
    # 创建一个新线程并给线程安排任务
    t = Thread(target=func)
    # 多线程状态为可以开始工作状态,具体的执行时间由CPU决定
    t.start()
    for i in range(1000, 2001):
        print(' main:', i, end=' ')

两条线程在同时运行:

再添加一个线程,执行效率就更高了

from threading import Thread  # 线程类


def func1():
    for i in range(1, 500):
        print(" fuc1:", i, end=' ')
def func2():
    for i in range(500, 1000):
        print(" fuc2:", i, end=' ')

if __name__ == '__main__':
    # 创建一个新线程并给线程安排任务
    t1 = Thread(target=func1)
    # 多线程状态为可以开始工作状态,具体的执行时间由CPU决定
    t1.start()
    t2 = Thread(target=func2)
    
    t2.start()
    for i in range(1000, 2001):
        print(' main:', i, end=' ')

传参

from threading import Thread  # 线程类


def func(name):
    for i in range(1, 500):
        print(name, i)


if __name__ == '__main__':
    # 创建一个新线程并给线程安排任务
    t1 = Thread(target=func,args=('没空调',))
    # 多线程状态为可以开始工作状态,具体的执行时间由CPU决定
    t2 = Thread(target=func,args=('没电扇',))

    t1.start()
    t2.start()


2.多线程写法二

from threading import Thread

# 继承Thread类


class MyThread1(Thread):
    # 重写run方法
    def run(self):  # run是固定的
        for i in range(1, 500):
            print(" 子线程1:", i, end=' ')


class MyThread2(Thread):
    # 重写run方法
    def run(self):  # run方法是固定的,当线程开始执行,默认执行run()
        for i in range(500, 1000):
            print(" 子线程2:", i, end=' ')


if __name__ == '__main__':
    t1 = MyThread1()
    t2 = MyThread2()
    # 开启线程
    # 当线程开始执行,默认执行run()方法
    t1.start()
    t2.start()

    for i in range(1000, 2001):
        print('主线程:', i, end=' ')

传参

from threading import Thread

# 继承Thread类

class MyThread(Thread):
    def __init__(self,args):
        Thread.__init__(self)
        self.args=args
    # 重写run方法
    def run(self):  # run方法是固定的,当线程开始执行,默认执行run()
        print(self.args)


if __name__ == '__main__':
    testname=('参数1',)
    #单个元素的元组要在后面加上逗号
    t = MyThread(testname)
  
    # 开启线程
    # 当线程开始执行,默认执行run()方法
    t.start()
   

派生类中重写了父类threading.Thread的run()方法,其他方法(除了构造函数)都不应在子类中被重写,换句话说,在子类中只有*init*()和run()方法被重写

​ Thread 的构造方法中,还可以有其他参数,可以看这个博客

3.join方法

再看个例子

from time import sleep
from threading import Thread
print('主线程执行代码')


def threadFunc(args1, args2):
    print("子线程 开始")
    print(f'线程函数的参数为:{args1},{args2}')
    sleep(5)
    print('子线程结束')


# 创建Thread类的实例对象
  # target 参数 指定 新线程要执行的函数
# 这里指定的函数对象只能写一个名字,不能后面加括号,
# 如果加括号就是直接在当前线程调用执行,而不是在新线程中执行了
thread = Thread(target=threadFunc, args=('参数1', '参数2'))

# 执行start 方法,就会创建新线程,
# 并且新线程会去执行入口函数里面的代码。
# 这时候 这个进程 有两个线程了


# target参数 是指定新线程的 入口函数, 新线程创建后就会 执行该入口函数里面的代码,
# args 指定了 传给 入口函数threadFunc 的参数。 线程入口函数 参数,必须放在一个元组里面,里面的元素依次作为入口函数的参数
thread.start()
print('主线程结束')

如果加入join方法

from time import sleep
from threading import Thread
print('主线程执行代码')


def threadFunc(args1, args2):
    print("子线程 开始")
    print(f'线程函数的参数为:{args1},{args2}')
    sleep(5)
    print('子线程结束')


# 创建Thread类的实例对象
  # target 参数 指定 新线程要执行的函数
# 这里指定的函数对象只能写一个名字,不能后面加括号,
# 如果加括号就是直接在当前线程调用执行,而不是在新线程中执行了
thread = Thread(target=threadFunc, args=('参数1', '参数2'))

# 执行start 方法,就会创建新线程,
# 并且新线程会去执行入口函数里面的代码。
# 这时候 这个进程 有两个线程了


# target参数 是指定新线程的 入口函数, 新线程创建后就会 执行该入口函数里面的代码,
# args 指定了 传给 入口函数threadFunc 的参数。 线程入口函数 参数,必须放在一个元组里面,里面的元素依次作为入口函数的参数
thread.start()



# 主线程的代码执行 子线程对象的join方法,
# 就会等待子线程结束,才继续执行下面的代码
thread.join()
print('主线程结束')

三.多进程

​ Manager获取子进程的运算结果

from multiprocessing import Process,Manager
from time import sleep

def f(taskno,return_dict):
    sleep(2)
    # 存放计算结果到共享对象中
    return_dict[taskno] = taskno

if __name__ == '__main__':
    manager = Manager()
    # 创建 类似字典的 跨进程 共享对象
    return_dict = manager.dict()
    plist = []
    for i in range(10):
        p = Process(target=f, args=(i,return_dict))
        p.start()
        plist.append(p)

    for p in plist:
        p.join()

    print('get result...')
    # 从共享对象中取出其他进程的计算结果
    for k,v in return_dict.items():
        print (k,v)


本文参考:

up主白月黑羽的B站博客

up主路飞学城IT的B站教程

多线程详解

以上是关于进程线程简单了解的主要内容,如果未能解决你的问题,请参考以下文章

进程线程同步异步

java 简单的代码片段,展示如何将javaagent附加到运行JVM进程

八.多进程与多线程

多线程编程

多线程编程

学习java第19天个人总结