进程和线程1

进程和线程

概念

在实现了线程的操作系统中,线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一个程序的执行实例就是一个进程。

进程(Process)

  • 是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。

进程和程序的关系

  • 程序是源代码编译后的文件,而这些文件存放在磁盘上。当程序被操作系统加载到内存中,就是进程,进程中存放着指令和数据(资源),它也是线程的容器

Linux中进程有父进程,子进程;Windows的进程是平等关系。

线程

  • 有时被称作轻量级进程(Lightweight Process, LWP), 是程序执行流最小单元
  • 一个标准的线程由线程ID, 当前指令指针(PC), 寄存器集合和堆栈组成。
  • 在许多系统中创建一个线程比创建一个进程快10-100倍。

进程,线程的理解

  • 现代操作系统提出进程的概念,每一个进程都认为自己独占所有计算机硬件资源。
  • 进程就是独立的王国,进程间不可以随便的共享数据。
  • 线程就是王国内的省份,同一个进程内的线程可以共享进程的资源,每一个线程拥有自己独立的对堆栈。

线程的状态

状态 含义
就绪(Ready) 线程能够运行,但在等待被调度。可能线程刚刚创建启动,或刚刚从阻塞中恢复,或者被其他线程抢占
运行(Running) 线程正在运行
阻塞(Blocked) 线程等待外部事件发生而无法运行,如I/O操作
终止(Terminated) 线程完成,或退出,或被

python中的进程和线程

进程会启动一个解释器进程,线程共享一个解释器进程。

eg:

  • 运行一个*.py文件,python解释器启动一个进程,来运行该py文件。

一. python的线程开发

python的线程开发使用标准库threading模块。

threading模块下的Thread类

#初始化函数
def __init__(self, group=None, target=None, name=None,
             args=(), kwargs=None, *, daemon=None)
        
        
常用参数名 含义
target 线程调用的对象,就是目标函数
name 为线程起名
args 为目标函数传递实参,元祖
kwargs 为目标函数关键字传参,字典

线程启动

import threading

def worker():
    print("wocker is running...")
    print("wocker Fineshed")
    
t = threading.Thread(target=worker, name="worker") #创建一个线程对象
t.start() # 启动线程

通过threading。Thread创建一个线程对象,target是目标函数,name可以指定名称。

但是线程没有启动,只是创建了一个线程对象,需要调用start方法启动。

线程之所以执行 函数,是因为线程中就是执行代码的,而最简单的封装就是函数,所以还是函数调用。

函数执行完,线程也就退出了。

如果不想让线程退出,或者线程一直工作 怎么办呢?
import threading
import time

def worker():
    while True:
        time.sleep(1)
        print("wocker is running...")
    print("wocker Fineshed")


t = threading.Thread(target=worker, name="worker")  # 创建一个线程对象
t.start()  # 启动线程

线程退出

Python没有提供线程退出的方法,线程在一下情况时退出:

  • 1.线程函数语句执行完毕
  • 2.线程函数中抛出未处理的异常
import threading
import time

def worker():
    count = 1
    while True:
        count += 1
        time.sleep(1)
        print("wocker is running...")
        if count > 5:
            # return #函数执行完毕
            # break #函数执行完毕
            raise RuntimeError("抛出未处理异常")
            


    print("wocker Fineshed")


t = threading.Thread(target=worker, name="worker")  # 创建一个线程对象
t.start()  # 启动线程

线程的传参

import threading
import time

def add(x, y):
    print("{} + {} = {}".format(x, y, x+y),
          threading.current_thread().ident # 当前线程的唯一ID
          )

thread1 = threading.Thread(target=add, name="add", args=(4, 5)) #创建线程对象



thread2 = threading.Thread(target=add, name="add", args=(4,), kwargs={"y":5}) #创建线程对象



thread3 = threading.Thread(target=add, name="add", args=(), kwargs={"x":4, "y":5}) #创建线程对象

thread2.start() # 启动
thread1.start() # 启动
thread3.start() # 启动

线程传参和函数传参没什么区别,本质上就是函数传参。

Threading模块的属性和方法

名称 含义
current_thread() 返回当前线程对象
main_thread() 返回主线程对象
active_count() 当前处于alive状态的线程个数(存活)【包括主线程】
enumerate() 返回所有活着的线程的列表,不包括已经终止的线程和未开始的线程【包括主线程】
get_ident() 返回当前线程的ID, 非0整数

Thread实例的属性和方法

名称 含义
name 只有一个名字,只是一个标识, 名称可以重名。getName()获取, setName()设置
ident 线程ID, 它是非0整数,线程启动后才会有ID, 否则为None。 线程退出,此ID依旧可以访问。此ID可以重复使用。
is_alive() f线程是否活着【True/False】
start() 启动线程。每一个线程必须并且只能执行该方法
run() 运行线程函数【只是在主线程内运行函数,并非启动一个线程来运行函数】

start方法和run方法测试:

示例:

start()方法

import threading
import time

def worker():
    count = 0
    while True:
        if count > 5:
            break
        time.sleep(1)
        count +=1
        print("wocker running...")


class MyThread(threading.Thread):

    def run(self) -> None:
        print("run......")
        super().run()

    def start(self) -> None:
        print("start.....")
        super().start()

t = MyThread(target=worker)
t.start()

####运行结果
start.....
run......
wocker running...
wocker running...
wocker running...
wocker running...
wocker running...
wocker running...

run方法:

import threading
import time

def worker():
    count = 0
    while True:
        if count > 5:
            break
        time.sleep(1)
        count +=1
        print("wocker running...")


class MyThread(threading.Thread):

    def run(self) -> None:
        print("run......")
        super().run()

    def start(self) -> None:
        print("start.....")
        super().start()

t = MyThread(target=worker)
t.run()

#运行结果
run......
wocker running...
wocker running...
wocker running...
wocker running...
wocker running...
wocker running...

start()方法会调用run()方法,而run()方法可以运行函数。

这两个方法看似功能重复了,这么看来留个方法就可以了,是这样吗???

start和run的区别:

#在线程函数中,增加打印当前线程

import threading
import time

def worker():
    count = 0
    while True:
        if count > 5:
            break
        time.sleep(1)
        count +=1
        print("wocker running...")
        print(threading.current_thread())


class MyThread(threading.Thread):

    def run(self) -> None:
        print("run......")
        super().run()

    def start(self) -> None:
        print("start.....")
        super().start()

t = MyThread(target=worker)
# t.run()
t.start()

使用start方法会启动一个线程Thread-1,来运行wocker函数;

而run方法直接在当前主线程内运行函数;

因此,必须使用start方法才能启动多个线程;

posted @ 2018-12-29 19:03  pyfaith  阅读(62)  评论(0)    收藏  举报