Saya pikir yang terbaik adalah memanggil join()
di utas Anda saat Anda mengharapkannya mati. Saya telah memberanikan diri untuk mengubah loop Anda menjadi akhir (Anda juga dapat menambahkan kebutuhan pembersihan apa pun yang diperlukan di sana). Variabel die
diperiksa pada setiap pass dan saat True
, program keluar.
import threading
import time
class MyThread (threading.Thread):
die = False
def __init__(self, name):
threading.Thread.__init__(self)
self.name = name
def run (self):
while not self.die:
time.sleep(1)
print (self.name)
def join(self):
self.die = True
super().join()
if __name__ == '__main__':
f = MyThread('first')
f.start()
s = MyThread('second')
s.start()
try:
while True:
time.sleep(2)
except KeyboardInterrupt:
f.join()
s.join()
KeyboardInterrupt dan sinyal hanya terlihat oleh proses (yaitu utas utama)... Lihat Ctrl-c yaitu KeyboardInterrupt untuk mematikan utas di python
Ctrl +C mengakhiri utas utama, tetapi karena utas Anda tidak dalam mode daemon, utas tetap berjalan, dan itu membuat proses tetap hidup. Kita bisa menjadikannya daemon:
f = FirstThread()
f.daemon = True
f.start()
s = SecondThread()
s.daemon = True
s.start()
Tapi kemudian ada masalah lain - setelah utas utama memulai utas Anda, tidak ada lagi yang bisa dilakukan. Jadi itu keluar, dan utasnya langsung hancur. Jadi, mari jaga utas utama tetap hidup:
import time
while True:
time.sleep(1)
Sekarang akan tetap mencetak 'pertama' dan 'kedua' sampai Anda menekan Ctrl +C .
Edit: seperti yang ditunjukkan oleh komentator, utas daemon mungkin tidak mendapat kesempatan untuk membersihkan hal-hal seperti file sementara. Jika Anda membutuhkannya, tangkap KeyboardInterrupt
pada utas utama dan minta koordinasi pembersihan dan penutupan. Namun dalam banyak kasus, membiarkan utas daemon mati tiba-tiba mungkin cukup baik.
Versi perbaikan dari jawaban @Thomas K:
- Mendefinisikan fungsi asisten
is_any_thread_alive()
menurut inti ini, yang dapat mengakhirimain()
otomatis.
Contoh kode:
import threading
def job1():
...
def job2():
...
def is_any_thread_alive(threads):
return True in [t.is_alive() for t in threads]
if __name__ == "__main__":
...
t1 = threading.Thread(target=job1,daemon=True)
t2 = threading.Thread(target=job2,daemon=True)
t1.start()
t2.start()
while is_any_thread_alive([t1,t2]):
time.sleep(0)