目次
中央プロセッサのスケジューリング単位は、単にプログラム内の端末実行です。後者は弟に相当する立場である。 " >中央プロセッサのスケジューリング単位は、単にプログラム内の端末実行です。後者は弟に相当する立場である。
1. スレッド モジュールのインポート: " >1. スレッド モジュールのインポート:
スレッドは、Thread メソッドを使用して作成することも、スレッド クラスの run メソッドをオーバーライドすることによって実装することもできます。スレッドは、シングル スレッドとマルチ スレッドに分割できます。 。 " >スレッドは、Thread メソッドを使用して作成することも、スレッド クラスの run メソッドをオーバーライドすることによって実装することもできます。スレッドは、シングル スレッドとマルチ スレッドに分割できます。 。
3.1 使用Thread方法来创建:" >3.1 使用Thread方法来创建:
3.2.1 单线程" >3.2.1 单线程
3.2.2 多线程
" >3.2.2 多线程
3.2 重写线程的类方法" >3.2 重写线程的类方法
4.线程锁" >4.线程锁
4.1 Lock" >4.1 Lock
4.2 RLock" >4.2 RLock
4.3 条件锁" >4.3 条件锁
5.信号量" >5.信号量
5.1 有界信号量" >5.1 有界信号量
5.2 无界信号量" >5.2 无界信号量
6.Event" >6.Event
7.local" >7.local
8.Timer" >8.Timer
总结" >总结
ホームページ バックエンド開発 Python チュートリアル 記事では、さまざまなスレッドの包括的な分析が提供されます

記事では、さまざまなスレッドの包括的な分析が提供されます

Aug 10, 2023 pm 04:13 PM
python


##はじめに

#今日のナレッジポイントを理解する前に、スレッド、プロセス、コルーチンについてご存知ですか? まず予備的な理解をしてみましょう。

#スレッド

中央プロセッサのスケジューリング単位は、単にプログラム内の端末実行です。後者は弟に相当する立場である。

Python のスレッドは役に立たないという人もいます。これは GIL のせいですが、盲目的に役に立たないわけではありません。結局のところ、これは IO 操作を実行するときに非常に役立ちます。は計算を実行するためだけに使用されます。これでは不十分なようです。スレッドの具体的な使用法を見てみましょう:

1. スレッド モジュールのインポート:

import threading as t
ログイン後にコピー

##2. スレッドの使用法 #
tt=t.Thread(group=None,target=None,name=None,args=(),kwargs={},name='',daemon=None)
group:线程组,必须是None
target:运行的函数
args:传入函数的参数元组
kwargs:传入函数的参数字典
name:线程名
daemon:线程是否随主线程退出而退出(守护线程)


Thread方法的返回值还有以下方法:
tt.start() : 激活线程,
tt.getName() : 获取线程的名称
tt.setName() :设置线程的名称 
tt.name : 获取或设置线程的名称
tt.is_alive() :判断线程是否为激活状态
tt.isAlive() :判断线程是否为激活状态
tt.setDaemon() 设置为守护线程(默认:False)
tt.isDaemon() :判断是否为守护线程
tt.ident :获取线程的标识符。只有在调用了start()方法之后该属性才有效
tt.join() :逐个执行每个线程,执行完毕后继续往下执行
tt.run() :自动执行线程对象


t的方法也有:
t.active_count(): 返回正在运行线程的数量
t.enumerate(): 返回正在运行线程的列表
t.current_thread().getName() 获取当前线程的名字
t.TIMEOUT_MAX 设置t的全局超时时间
ログイン後にコピー

見てみましょう:


記事では、さまざまなスレッドの包括的な分析が提供されます


##3 . スレッドの作成

スレッドは、Thread メソッドを使用して作成することも、スレッド クラスの run メソッドをオーバーライドすることによって実装することもできます。スレッドは、シングル スレッドとマルチ スレッドに分割できます。 。

3.1 使用Thread方法来创建:

3.1.1 单线程
def xc():
    for y in range(100):
        print('运行中'+str(y))
tt=t.Thread(target=xc,args=()) #方法加入到线程
tt.start()  #开始线程
tt.join() #等待子线程结束
ログイン後にコピー
3.1.2 多线程
def xc(num):
    print('运行:'+str(num))
c=[]
for y in range(100):
    tt=t.Thread(target=xc,args=(y,))
    tt.start() #开始线程
    c.append(tt) #创建列表并添加线程
for x in c:
    x.join()  #等待子线程结束
ログイン後にコピー

3.2 重写线程的类方法

3.2.1 单线程
class Xc(t.Thread): #继承Thread类
    def __init__(self):
        super(Xc, self).__init__() 
    def run(self):  #重写run方法
        for y in range(100):
            print('运行中'+str(y))
x=Xc() 
x.start() #开始线程
x.join()  #等待子线程结束


也可以这么写:
Xc().run() 和上面的效果是一样的
ログイン後にコピー
3.2.2 多线程
class Xc(t.Thread): #继承Thread类
    def __init__(self):
        super(Xc, self).__init__() 
    def run(self,num):  #重写run方法
        print('运行:'+str(num))
x=Xc()
for y in range(10):
    x.run(y) #运行
ログイン後にコピー

4.线程锁

为什么要加锁,看了这个你就知道了:

記事では、さまざまなスレッドの包括的な分析が提供されます

多线程在运行时同时访问一个对象会产生抢占资源的情况,所以我们必须得束缚它,所以就要给他加一把锁把他锁住,这就是同步锁。要了解锁,我们得先创建锁,线程中有两种锁:Lock和RLock。

4.1 Lock

使用方法:

# 获取锁
当获取不到锁时,默认进入阻塞状态,设置超时时间,直到获取到锁,后才继续。非阻塞时,timeout禁止设置。如果超时依旧未获取到锁,返回False。
Lock.acquire(blocking=True,timeout=1)   


#释放锁,已上锁的锁,会被设置为unlocked。如果未上锁调用,会抛出RuntimeError异常。
Lock.release()
ログイン後にコピー

互斥锁,同步数据,解决多线程的安全问题:

n=10
lock=t.Lock()
def xc(num):
    lock.acquire()
    print('运行+:'+str(num+n))
    print('运行-:'+str(num-n))
    lock.release()
c=[]
for y in range(10):
    tt=t.Thread(target=xc,args=(y,))
    tt.start()
    c.append(tt)
for x in c:
    x.join()
ログイン後にコピー

这样就显得有条理了,而且输出也是先+后-。Lock在一个线程中多次使用同一资源会造成死锁。

死锁问题:

n=10
lock1=t.Lock()
lock2=t.Lock()
def xc(num):
  lock1.acquire()
  print('运行+:'+str(num+n))
  lock2.acquire()
  print('运行-:'+str(num-n))
  lock2.release()
  lock1.release()
c=[]
for y in range(10):
  tt=t.Thread(target=xc,args=(y,))
  tt.start()
  c.append(tt)
for x in c:
  x.join()
ログイン後にコピー


4.2 RLock

相比Lock它可以递归,支持在同一线程中多次请求同一资源,并允许在同一线程中被多次锁定,但是acquire和release必须成对出现。

使用递归锁来解决死锁:

n=10
lock1=t.RLock()
lock2=t.RLock()
def xc(num):
  lock1.acquire()
  print('运行+:'+str(num+n))
  lock2.acquire()
  print('运行-:'+str(num-n))
  lock2.release()
  lock1.release()
c=[]
for y in range(10):
  tt=t.Thread(target=xc,args=(y,))
  tt.start()
  c.append(tt)
for x in c:
  x.join()
ログイン後にコピー

这时候,输出变量就变得仅仅有条了,不在随意抢占资源。关于线程锁,还可以使用with更加方便:

#with上下文管理,锁对象支持上下文管理
with lock:   #with表示自动打开自动释放锁
  for i in range(10): #锁定期间,其他人不可以干活
    print(i)
  #上面的和下面的是等价的
if lock.acquire(1):#锁住成功继续干活,没有锁住成功就一直等待,1代表独占
  for i in range(10): #锁定期间,其他线程不可以干活
    print(i)
  lock.release() #释放锁
ログイン後にコピー


4.3 条件锁

等待通过,Condition(lock=None),可以传入lock或者Rlock,默认Rlock,使用方法:

Condition.acquire(*args)      获取锁


Condition.wait(timeout=None)  等待通知,timeout设置超时时间


Condition.notify(num)唤醒至多指定数目个数的等待的线程,没有等待的线程就没有任何操作


Condition.notify_all()  唤醒所有等待的线程 或者notifyAll()
ログイン後にコピー
def ww(c):
  with c:
    print('init')
    c.wait(timeout=5) #设置等待超时时间5
    print('end')
def xx(c):
  with c:
    print('nono')
    c.notifyAll() #唤醒所有线程
    print('start')
    c.notify(1) #唤醒一个线程
    print('21')
c=t.Condition() #创建条件
t.Thread(target=ww,args=(c,)).start()
t.Thread(target=xx,args=(c,)).start()
ログイン後にコピー

这样就可以在等待的时候唤醒函数里唤醒其他函数里所存在的其他线程了。


5.信号量

信号量可以分为有界信号量和无解信号量,下面我们来具体看看他们的用法:

5.1 有界信号量

它不允许使用release超出初始值的范围,否则,抛出ValueError异常。

#构造方法。value为初始信号量。value小于0,抛出ValueError异常
b=t.BoundedSemaphore(value=1)  


#获取信号量时,计数器减1,即_value的值减少1。如果_value的值为0会变成阻塞状态。获取成功返回True
BoundedSemaphore.acquire(blocking=True,timeout=None)  


#释放信号量,计数器加1。即_value的值加1,超过初始化值会抛出异常ValueError。
BoundedSemaphore.release()  


#信号量,当前信号量
BoundedSemaphore._value
ログイン後にコピー

記事では、さまざまなスレッドの包括的な分析が提供されます

可以看到了多了个release后报错了。


5.2 无界信号量

它不检查release的上限情况,只是单纯的加减计数器。

記事では、さまざまなスレッドの包括的な分析が提供されます

可以看到虽然多了个release,但是没有问题,而且信号量的数量不受限制。


6.Event

线程间通信,通过线程设置的信号标志(flag)的False 还是True来进行操作,常见方法有:

event.set()      flag设置为True
event.clear()  flag设置为False
event.is_set()  flag是否为True,如果 event.isSet()==False将阻塞线程;
设置等待flag为True的时长,None为无限等待。等到返回True,未等到超时则返回False
event.wait(timeout=None)
ログイン後にコピー

下面通过一个例子具体讲述:

import time
e=t.Event()
def ff(num):
  while True:
    if num<5:
      e.clear()   #清空信号标志
      print(&#39;清空&#39;)
    if num>=5:
      e.wait(timeout=1) #等待信号标志为真
      e.set()
      print(&#39;启动&#39;)
      if e.isSet(): #如果信号标志为真则清除标志
        e.clear()
        print(&#39;停止&#39;)
    if num==10:
      e.wait(timeout=3)
      e.clear()
      print(&#39;退出&#39;)
      break
    num+=1
    time.sleep(2)
ff(1)
ログイン後にコピー

記事では、さまざまなスレッドの包括的な分析が提供されます

设置延迟后可以看到效果相当明显,我们让他干什么事他就干什么事。


7.local

可以为各个线程创建完全属于它们自己的变量(线程局部变量),而且它们的值都在当前调用它的线程当中,以字典的形式存在。下面我们来看下:

l=t.local()  #创建一个线程局部变量
def ff(num):
  l.x=100  #设置l变量的x方法的值为100
  for y in range(num):
    l.x+=3 #改变值
  print(str(l.x))


for y in range(10):
  t.Thread(target=ff,args=(y,)).start() #开始执行线程
ログイン後にコピー

那么,可以将变量的x方法设为全局变量吗?我们来看下:

記事では、さまざまなスレッドの包括的な分析が提供されます

可以看出他报错了,产生错误的原因是因为这个类中没有属性x,我们可以简单的理解为局部变量就只接受局部。


8.Timer

设置定时计划,可以在规定的时间内反复执行某个方法。他的使用方法是:

t.Timer(num,func,*args,**kwargs) #在指定时间内再次重启程序
ログイン後にコピー

下面我们来看下:

def f():
  print(&#39;start&#39;)
  global t #防止造成线程堆积导致最终程序退出
  tt= t.Timer(3, f)
  tt.start()
f()
ログイン後にコピー

这样就达到了每三秒执行一次f函数的效果。


总结

通过对线程的全面解析我们了解到了线程的重要性,它可以将我们复杂的问题变得简单化,对于喜欢玩爬虫的小伙伴们可以说是相当有用了,本文基本覆盖了线程的所有概念,希望能帮到大家。

以上が記事では、さまざまなスレッドの包括的な分析が提供されますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

PHPおよびPython:コードの例と比較 PHPおよびPython:コードの例と比較 Apr 15, 2025 am 12:07 AM

PHPとPythonには独自の利点と短所があり、選択はプロジェクトのニーズと個人的な好みに依存します。 1.PHPは、大規模なWebアプリケーションの迅速な開発とメンテナンスに適しています。 2。Pythonは、データサイエンスと機械学習の分野を支配しています。

Python vs. JavaScript:コミュニティ、ライブラリ、リソース Python vs. JavaScript:コミュニティ、ライブラリ、リソース Apr 15, 2025 am 12:16 AM

PythonとJavaScriptには、コミュニティ、ライブラリ、リソースの観点から、独自の利点と短所があります。 1)Pythonコミュニティはフレンドリーで初心者に適していますが、フロントエンドの開発リソースはJavaScriptほど豊富ではありません。 2)Pythonはデータサイエンスおよび機械学習ライブラリで強力ですが、JavaScriptはフロントエンド開発ライブラリとフレームワークで優れています。 3)どちらも豊富な学習リソースを持っていますが、Pythonは公式文書から始めるのに適していますが、JavaScriptはMDNWebDocsにより優れています。選択は、プロジェクトのニーズと個人的な関心に基づいている必要があります。

Dockerの原則の詳細な説明 Dockerの原則の詳細な説明 Apr 14, 2025 pm 11:57 PM

DockerはLinuxカーネル機能を使用して、効率的で孤立したアプリケーションランニング環境を提供します。その作業原則は次のとおりです。1。ミラーは、アプリケーションを実行するために必要なすべてを含む読み取り専用テンプレートとして使用されます。 2。ユニオンファイルシステム(UnionFS)は、違いを保存するだけで、スペースを節約し、高速化する複数のファイルシステムをスタックします。 3.デーモンはミラーとコンテナを管理し、クライアントはそれらをインタラクションに使用します。 4。名前空間とcgroupsは、コンテナの分離とリソースの制限を実装します。 5.複数のネットワークモードは、コンテナの相互接続をサポートします。これらのコア概念を理解することによってのみ、Dockerをよりよく利用できます。

Visual StudioコードはPythonで使用できますか Visual StudioコードはPythonで使用できますか Apr 15, 2025 pm 08:18 PM

VSコードはPythonの書き込みに使用でき、Pythonアプリケーションを開発するための理想的なツールになる多くの機能を提供できます。ユーザーは以下を可能にします。Python拡張機能をインストールして、コードの完了、構文の強調表示、デバッグなどの関数を取得できます。デバッガーを使用して、コードを段階的に追跡し、エラーを見つけて修正します。バージョンコントロールのためにGitを統合します。コードフォーマットツールを使用して、コードの一貫性を維持します。糸くずツールを使用して、事前に潜在的な問題を発見します。

ターミナルVSCODEでプログラムを実行する方法 ターミナルVSCODEでプログラムを実行する方法 Apr 15, 2025 pm 06:42 PM

VSコードでは、次の手順を通じて端末でプログラムを実行できます。コードを準備し、統合端子を開き、コードディレクトリが端末作業ディレクトリと一致していることを確認します。プログラミング言語(pythonのpython your_file_name.pyなど)に従って実行コマンドを選択して、それが正常に実行されるかどうかを確認し、エラーを解決します。デバッガーを使用して、デバッグ効率を向上させます。

VSCODE拡張機能は悪意がありますか? VSCODE拡張機能は悪意がありますか? Apr 15, 2025 pm 07:57 PM

VSコード拡張機能は、悪意のあるコードの隠れ、脆弱性の活用、合法的な拡張機能としての自慰行為など、悪意のあるリスクを引き起こします。悪意のある拡張機能を識別する方法には、パブリッシャーのチェック、コメントの読み取り、コードのチェック、およびインストールに注意してください。セキュリティ対策には、セキュリティ認識、良好な習慣、定期的な更新、ウイルス対策ソフトウェアも含まれます。

Python:自動化、スクリプト、およびタスク管理 Python:自動化、スクリプト、およびタスク管理 Apr 16, 2025 am 12:14 AM

Pythonは、自動化、スクリプト、およびタスク管理に優れています。 1)自動化:OSやShutilなどの標準ライブラリを介してファイルバックアップが実現されます。 2)スクリプトの書き込み:Psutilライブラリを使用してシステムリソースを監視します。 3)タスク管理:スケジュールライブラリを使用してタスクをスケジュールします。 Pythonの使いやすさと豊富なライブラリサポートにより、これらの分野で優先ツールになります。

Windows 8でコードを実行できます Windows 8でコードを実行できます Apr 15, 2025 pm 07:24 PM

VSコードはWindows 8で実行できますが、エクスペリエンスは大きくない場合があります。まず、システムが最新のパッチに更新されていることを確認してから、システムアーキテクチャに一致するVSコードインストールパッケージをダウンロードして、プロンプトとしてインストールします。インストール後、一部の拡張機能はWindows 8と互換性があり、代替拡張機能を探すか、仮想マシンで新しいWindowsシステムを使用する必要があることに注意してください。必要な拡張機能をインストールして、適切に動作するかどうかを確認します。 Windows 8ではVSコードは実行可能ですが、開発エクスペリエンスとセキュリティを向上させるために、新しいWindowsシステムにアップグレードすることをお勧めします。

See all articles