~~並發編程(八):開啟線程~~


進擊のpython

*****

並發編程——開啟進程


學知識除了要縱向吸收,還要學會橫向對比

這樣類比學習就容易簡單的多

線程的學習就可以根據進程的學習來進行參考

這一節我們可以嘗試着使用threading模塊開啟線程

通過掌握threading模塊開啟線程的兩種方式

(我連上一句話都是照着線程的那個文章扒下來的)


threading模塊

multiprocess模塊的完全模仿了threading模塊的接口,二者在使用層面,有很大的相似性,因而不再詳細介紹


Thread類

class Thread:

    def __init__(self, group=None, target=None, name=None,
                 args=(), kwargs=None, *, daemon=None):
        if kwargs is None:
            kwargs = {}
        self._target = target
        self._name = str(name or _newname())
        self._args = args
        self._kwargs = kwargs
        if daemon is not None:
            self._daemonic = daemon
        else:
            self._daemonic = current_thread().daemon
        self._ident = None
        self._tstate_lock = None
        self._started = Event()
        self._is_stopped = False
        self._initialized = True
        # sys.stderr is not stored in the class like
        # sys.exc_info since it can be changed between instances
        self._stderr = _sys.stderr
        # For debugging and _after_fork()
        _dangling.add(self)

介紹一下參數:

group:參數未使用,值始終是None

target:表示調用對象,即子線程要執行的任務(就是塞進去一個你想執行的函數)

args:表示調用對象的位置參數元祖(就是對函數進行傳參)

kwargs:表示調用對象的字典(就是對函數進行傳參)

name:子線程的名字

介紹一下屬性:

t.daemon:默認值為False,如果設為True,代表p為后台運行的守護進程

​ 當p的父進程終止時,p也隨之終止,並且設定為True后,p不能創建自己的新進程

​ 必須在start之前設置
​ 2.name:線程的名稱

def start(self):
    if not self._initialized:
        raise RuntimeError("thread.__init__() not called")

    if self._started.is_set():
        raise RuntimeError("threads can only be started once")
    with _active_limbo_lock:
        _limbo[self] = self
    try:
        _start_new_thread(self._bootstrap, ())
    except Exception:
        with _active_limbo_lock:
            del _limbo[self]
        raise
    self._started.wait()


def run(self):
    try:
        if self._target:
            self._target(*self._args, **self._kwargs)
    finally:
        # Avoid a refcycle if the thread is running a function with
        # an argument that has a member that points to the thread.
        del self._target, self._args, self._kwargs


def join(self, timeout=None):
    if not self._initialized:
        raise RuntimeError("Thread.__init__() not called")
    if not self._started.is_set():
        raise RuntimeError("cannot join thread before it is started")
    if self is current_thread():
        raise RuntimeError("cannot join current thread")

    if timeout is None:
        self._wait_for_tstate_lock()
    else:
        # the behavior of a negative timeout isn't documented, but
        # historically .join(timeout=x) for x<0 has acted as if timeout=0
        self._wait_for_tstate_lock(timeout=max(timeout, 0))


def is_alive(self):
    assert self._initialized, "Thread.__init__() not called"
    if self._is_stopped or not self._started.is_set():
        return False
    self._wait_for_tstate_lock(False)
    return not self._is_stopped


def isAlive(self):
    import warnings
    warnings.warn('isAlive() is deprecated, use is_alive() instead',
                  PendingDeprecationWarning, stacklevel=2)
    return self.is_alive()


@property
def daemon(self):
    assert self._initialized, "Thread.__init__() not called"
    return self._daemonic


@daemon.setter
def daemon(self, daemonic):
    if not self._initialized:
        raise RuntimeError("Thread.__init__() not called")
    if self._started.is_set():
        raise RuntimeError("cannot set daemon status of active thread")
    self._daemonic = daemonic
    

接下來介紹一下方法:

start():啟動線程,並調用該子線程中的run()

run(): 線程啟動時運行的方法,正是它去調用target指定的函數,我們自定義類的類中一定要實現該方法

is_alive():如果p仍然運行,返回True

join([timeout]):主線程等待p終止(強調:是主線程處於等的狀態,而p是處於運行的狀態)

​ timeout是可選的超時時間


Thread的使用

首先很重要的一點就是,在windows系統,線程的開啟必須放到if name == 'main':的下面

第一種方法

from threading import Thread


def func(name, *args, **kwargs):
    print(f'{name}執行!')
    pass


if __name__ == '__main__':
    p = Thread(target=func, args=('子線程',))
    p.start()
    print('我是主線程... ...')

在主進程中創建一個子進程,用來執行函數func,並對函數進行傳參

然后利用start進行聲明子進程

第二種方法

from threading import Thread


class Mythread(Thread):
    """這是Mythread"""

    def __init__(self, name):
        super().__init__()
        self.name = name

    def run(self):
        print(f'{self.name}執行!')


if __name__ == '__main__':
    p = Mythread('子線程')
    p.start()
    print('我是主線程... ...')

這種方法用的太少了,就看一下了解一下就行

更多的還是第一種方法的使用


*****
*****


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM