python3 利用threading.Thread实现多线程编程

多线程可以将运行时间长的任务放到后台,转而执行其他任务,以提高效率基础概念可以看一下菜鸟的教程

https://www.runoob.com/python3/python3-multithreading.html 这里我做了一个简单的界面,便于理解多线程

python thread join 超时 python threading.thread_tkinter


界面是依赖tkinter库实现的。

其中包含三个按键和四个文本框

实现的功能是:

主线程使界面一直显示
开启线程1 的按钮 控制 线程1 在左上角文本框中每隔三秒打印一次时间
开启线程1 的按钮 控制 线程1 在右上角文本框中每隔三秒打印一次时间
选择文件的按钮 新建一个线程用于选择一个文件,并把文件目录打印在中间文本框里
还有无需按钮触发直接启动的线程,任务是在最下方文本框里每隔两秒打印一次时间

效果是:证明线程是并行的,即同一时间可以执行多项任务
虽然电脑是单核的,但是多线程之间切换的速度非常快以至于感受不到任务在切换执行,因此形成一种同时执行的感觉
比如上图中,19:22,19:25,19:27三个时间都同时在两个文本框中打印,说明几个线程在同步进行。

代码如下所示

这里建立线程的技巧是:
在button的command函数上不传递参数,而是调用一个传递参数并建立线程的函数
如果command函数带参数,则线程会在程序运行开始时自动执行,如果按下按钮,则会再建一个线程,相当于多建了一个线程。

from tkinter import *
from tkinter import scrolledtext,filedialog
import threading
import time
class MY_THREADING_TK():
    #构造函数
    def __init__(self,tkname):
        self.tkname = tkname
    #对窗口进行控件初始化
    def tk_init(self):
        #父窗口属性
        self.tkname.title('多线程测试')
        self.tkname.geometry('700x400+200+100')
        #控件
        #文本框
        self.text_one=scrolledtext.ScrolledText(self.tkname,width=38,height=10)
        self.text_one.place(x=50,y=100)
        self.text_two=scrolledtext.ScrolledText(self.tkname,width=38,height=10)
        self.text_two.place(x=350,y=100)
        self.file_path_text=Text(self.tkname,width=40,height=2)
        self.file_path_text.place(x=300,y=250)
        self.auto_print_text=scrolledtext.ScrolledText(self.tkname,width=80,height=5)
        self.auto_print_text.place(x=50,y=300)
        #标签
        button_one=Button(self.tkname,text='开启线程1',width=20,bg='lightblue',command=self.new_thread_one)
        button_one.place(x=100,y=50)
        button_two=Button(self.tkname,text='开启线程2',width=20,bg='lightblue',command=self.new_thread_two)
        button_two.place(x=400,y=50)
        file_button=Button(self.tkname,text='选择文件',width=20,bg='lightblue',command=self.file_choose_thread)
        file_button.place(x=100,y=250)
      
    def new_thread_one(self):
        new_thread=threading.Thread(target=self.thread,args=(self.text_one,3))
        new_thread.start()
    def new_thread_two(self):
        new_thread=threading.Thread(target=self.thread,args=(self.text_two,3))
        new_thread.start()
    def file_choose_thread(self):
        new_thread=threading.Thread(target=self.file_thread)
        new_thread.start()
    def auto_print_time_thread(self):
        new_thread=threading.Thread(target=self.print_time)
        new_thread.start()

    def print_time(self):
        while True:
            self.auto_print_text.insert(END,time.ctime(time.time())+'\n')
            self.auto_print_text.see(END)
            self.auto_print_text.update()
            time.sleep(2)
    def thread(self,text,sec):
        text.delete('1.0','end')
        while True:
            text.insert(END,time.ctime(time.time())+'\n')
            text.see(END)
            text.update()
            time.sleep(sec)
    def file_thread(self):
        self.file_path_text.insert(END,filedialog.askopenfilename())

mastertk = Tk()  #新建一个父窗口
my_tk = MY_THREADING_TK(mastertk)
my_tk.tk_init()
my_tk.auto_print_time_thread()
mastertk.mainloop()

另有需要注意的是,线程1、线程2之间无干涉,但是如果建立线程选择文件,但是又没选中,停留在文件选择对话框的时候,是不能执行线程1、2的,这是因为filedialog这个类本身不支持多线程。