Raspberry Pi 3 & Python 開発ブログ☆彡

Raspberry Pi 3の使い方、設定をわかりやすく解説。Raspberry Pi3 Model B(Element14版)、Raspbian 8.0(NOOBS Ver1.9.2)を使用して開発中。

【スポンサーリンク】

Pythonプログラム入門(スレッド)

【スポンサーリンク】

今日はPythonでスレッド処理の構文を紹介したいと思います。

 

スレッドとは並列処理のことです。スレッドを使わなければ、基本的に上から下に順番にコードが実行されます。動作的にわかりやすいですが、順次処理ですのですべての処理が完了するまでに時間がかかります。スレッドを使うと動作は複雑になりますが、並列処理ですので、断然処理完了までのスピードは速くなります。

 

処理時間に余裕があり、スレッドを使う必要がなければ、スレッドは使わない方がいいと思います。なぜなら、スレッドを使うと格段に難易度が上がるからです。スレッドを使ったことにより、極まれにしか発生しないバグが発生する場合があり、バグの解析にかなり時間を要することがあります。

 スレッド

スレッドを作成するには、threading.Threadを継承したクラスを作成します。このクラスのインスタンスを作成し、クラス名.start()のコードを実行することで、このクラスゾットのrun関数が実行される動きになります。もちろん並列処理です。

 

下記はMyThread1とMyThread2という2つのクラスを作成しています。

・MyThread1は5秒後にcount変数に5を加算する

・MyThread2は10秒後にcount変数に10を加算する

このふたつのクラスを同時にスタートさせます。並列処理ですので、5秒後にcount変数は5加算され、さらに5秒後(スタートから10秒後)に10加算され、最終的に15という結果が表示されます。

もしこれが順次処理であれば、5秒後に5加算され、さらに10秒後(スタートから15秒後)に10加算される動きとなります。当たり前ですが、順次処理の方が処理完了までの時間が遅くなります。

 

# -*- coding: utf-8 -*-
import threading, time, datetime

g_cnt = 0

class MyThread1(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.name = "MyThread1"

    def run(self):
        global g_cnt

        # read
        print(self.name + ':value -> ' + str(g_cnt)) + ' :time -> ' + str(datetime.datetime.now())
        time.sleep(5)

        # write
        g_cnt = g_cnt + 5
        print(self.name + ':value -> ' + str(g_cnt)) + ' :time -> ' + str(datetime.datetime.now())

class MyThread2(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.name = "MyThread2"

    def run(self):
        global g_cnt

        # read
        print(self.name + ':value -> ' + str(g_cnt)) + ' :time -> ' + str(datetime.datetime.now())

        time.sleep(10)

        # write
        g_cnt = g_cnt + 10
        print(self.name + ':value -> ' + str(g_cnt)) + ' :time -> ' + str(datetime.datetime.now())

thread1 = MyThread1()
thread2 = MyThread2()

thread1.start()
thread2.start()

thread1.join()
thread2.join()

print('Result' + ':value -> ' + str(g_cnt)) + ' :time -> ' + str(datetime.datetime.now())

このコードを実行すると以下の結果になります。MyThread1とMyThread2が交互に出てきます。並列処理になっていることがわかりますね。

MyThread1:value -> 0 :time -> 2016-09-04 17:11:23.087223
MyThread2:value -> 0 :time -> 2016-09-04 17:11:23.087994
MyThread1:value -> 5 :time -> 2016-09-04 17:11:28.092923
MyThread2:value -> 15 :time -> 2016-09-04 17:11:33.098486
Result::value -> 15 :time -> 2016-09-04 17:11:33.098957

 

次回は、排他制御について記載しようと思います。