使用Python进行多任务_线程篇

线程介绍

  • 进程是分配资源的最小单位,线程是程序执行的最小单位
  • 一个进程最少有一个线程,线程自己没有资源,共享进程的资源

多线程完成多任务

  1. 导入线程模块 import threading
  2. 创建线程对象 threading.Tread(target=[])
  3. 启动 对象.start()
import threading
import time
def coding():
    for i in range(3):
        print('coding')
        time.sleep(0.2)

def music():
    for i in range(3):
        print('music')
        time.sleep(0.2)

coding_thread = threading.Thread(target=coding)
music_thread = threading.Thread(target=music)

coding_thread.start()
music_thread.start()


codingmusic

codingmusic

music
coding
def coding(num):
    for i in range(3):
        print('coding')
        time.sleep(0.2)

def music(count):
    for i in range(3):
        print('music')
        time.sleep(0.2)

coding_thread = threading.Thread(target=coding, args=(3,))
music_thread = threading.Thread(target=music, kwargs={'count':4})

coding_thread.start()
music_thread.start()

codingmusic

codingmusic

coding
music

主线程和子线程的结束顺序

  • 主线程会等待所有子线程之行结束后再结束

设置守护主线程的两种方法

work_thread = threading.Thread(target=work)
work_thread.start()
time.sleep(1)
print('main thread is over')
work_thread = threading.Thread(target=work)
work_thread.setDaemon(True)
work_thread.start()
time.sleep(1)
print('main thread is over')

线程之间的执行顺序

  • 是无序的

通过获取线程信息来看一看是不是这样

def get_info():
    time.sleep(0.5)
    current_thread = threading.current_thread()
    print(current_thread)
for i in range(10):
    sub_thread = threading.Thread(target=get_info)
    sub_thread.start()
<Thread(Thread-34, started 6253195264)>
<Thread(Thread-38, started 6320500736)><Thread(Thread-41, started 6370979840)><Thread(Thread-36, started 6286848000)><Thread(Thread-40, started 6354153472)><Thread(Thread-42, started 6387806208)><Thread(Thread-39, started 6337327104)>



<Thread(Thread-37, started 6303674368)>


<Thread(Thread-35, started 6270021632)><Thread(Thread-33, started 6236368896)>

线程之间共享全局变量

my_list = []


def write_data():
    for i in range(5):
        my_list.append(i)
        print("add:", i)
    print('write:', my_list)


def read_data():
    print('read:', my_list)


if __name__ == '__main__':
    # 创建写进程
    write_thread = threading.Thread(target=write_data)
    # 创建读进程
    read_thread = threading.Thread(target=read_data)
    write_thread.start()
    time.sleep(1)
    read_thread.start()
add: 0
add: 1
add: 2
add: 3
add: 4
write: [0, 1, 2, 3, 4]
read: [0, 1, 2, 3, 4]

线程之间共享全局变量数据出现错误

  • 定义两个函数,循环100w次,每次全局变量+1
  • 创建两个子线程执行对应函数,查看计算结果
g_num = 0


def func_1():
    for i in range(1000000):
        global g_num
        g_num += 1
    print("func_1", g_num)
    
    
def func_2():
    for i in range(1000000):
        global g_num
        g_num += 1
    print("func_2", g_num)
if __name__ == '__main__':
    sum1_thread = threading.Thread(target=func_1)
    sum2_thread = threading.Thread(target=func_2)
    sum1_thread.start()
    sum2_thread.start()
func_1func_2 1345500
 1489972

在把改变的全局变量返回给全局变量之前,就被另一个线程拿走并进行加1的操作,就会导致出错

使用线程同步来解决

线程协同步调——线程同步

  • 按照预定的先后次序进行运行
  • 保证同一时刻只能有一个线程去操作全局变量
  • 使用互斥锁

互斥锁

  • 对共享的数据进行锁定,保证同一时刻只有一个线程去操作
  • 需要竞争,只有抢到钥匙的人才能享用资源,否则就得等
g_num = 0


def func_1():
    # 上锁
    mutex.acquire()
    for i in range(1000000):
        global g_num
        g_num += 1
    print("func_1", g_num)
    # 解锁
    mutex.release()
    
    
def func_2():
    # 上锁
    mutex.acquire()
    for i in range(1000000):
        global g_num
        g_num += 1
    print("func_2", g_num)
    # 解锁
    mutex.release()
if __name__ == '__main__':
    # 创建一把锁
    mutex = threading.Lock()
    
    sum1_thread = threading.Thread(target=func_1)
    sum2_thread = threading.Thread(target=func_2)
    sum1_thread.start()
    sum2_thread.start()
func_1 1000000
func_2 2000000

死锁

  • 一种现象,一直等待对方释放锁的情况
  • 导致程序停止响应
g_num = 0


def func_1():
    print("func_1....")
    # 上锁
    mutex.acquire()
    for i in range(1000000):
        global g_num
        g_num += 1
    print("func_1", g_num)
    # 解锁
#     mutex.release()
    
    
def func_2():
    print("func_2...")
    # 上锁
    mutex.acquire()
    for i in range(1000000):
        global g_num
        g_num += 1
    print("func_2", g_num)
    # 解锁
#     mutex.release()
if __name__ == '__main__':
    # 创建一把锁
    mutex = threading.Lock()
    
    sum1_thread = threading.Thread(target=func_1)
    sum2_thread = threading.Thread(target=func_2)
    sum1_thread.start()
    sum2_thread.start()
func_1....
func_2...
func_1 1000000

进程和线程的对比

  1. 关系对比
  • 线程依附于进程,没有进程就没有线程
  • 一个进程至少有一个线程,进程可以创建多个线程
  1. 区别关系
  • 进程不共享全局变量,线程共享
  • 线程存在资源竞争,使用互斥锁解决
  • 创建进程的资源开销更大
  • 进程是资源分配基本单位,线程是执行的资本单位
  • 线程不可独立执行,依存于进程
  1. 优缺点对比
  • 进程
    • 可以用多核(运行qq或微信这两个进程可以用cpu的多个核,并行)
    • 资源大
  • 线程
    • 资源开销小
    • 不能多核,需要排队
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 很抱歉,我之前回答的还是这个问题。以下是一个稍微复杂一点的 Python线程实例,可以用来计算一个矩阵的乘积: ```python import threading import numpy as np # 定义矩阵的大小 MATRIX_SIZE = 1000 # 初始化两个随机矩阵 matrix_a = np.random.rand(MATRIX_SIZE, MATRIX_SIZE) matrix_b = np.random.rand(MATRIX_SIZE, MATRIX_SIZE) # 初始化结果矩阵 result_matrix = np.zeros((MATRIX_SIZE, MATRIX_SIZE)) # 定义一个函数,用来计算矩阵的乘积 def multiply(start, end): for i in range(start, end): for j in range(MATRIX_SIZE): for k in range(MATRIX_SIZE): result_matrix[i][j] += matrix_a[i][k] * matrix_b[k][j] # 定义线程数量 NUM_THREADS = 4 # 计算每个线程需要计算的行数 rows_per_thread = MATRIX_SIZE // NUM_THREADS # 创建线程列表 threads = [] # 启动线程 for i in range(NUM_THREADS): start = i * rows_per_thread end = (i + 1) * rows_per_thread t = threading.Thread(target=multiply, args=(start, end)) threads.append(t) t.start() # 等待所有线程结束 for t in threads: t.join() # 检查结果是否正确 expected_result = np.dot(matrix_a, matrix_b) assert np.array_equal(result_matrix, expected_result) # 输出 Done 表示程序执行完毕 print("Done") ``` 这个例子首先初始化两个随机矩阵,然后定义一个函数 multiply,用来计算这两个矩阵的乘积。然后,它将矩阵分成若干个部分,每个部分分配给一个线程来计算。最后,它等待所有线程结束,检查结果是否正确,并输出 Done 表示程序执行完毕。 希望这个例子能够帮助您更好地理解 Python线程使用方法。 ### 回答2: Python线程实例是指在Python编程语言使用线程进行并发编程的实例。在Python中,可以使用内置的threading模块来创建和管理多线程。 通过创建多线程,可以在程序中同时执行多个任务。这对于需要同时处理多个任务的情况非常有用。例如,在下载大文件时,可以使用线程同时下载多个文件,加快下载速度。此外,多线程还可以用于处理网络请求、图像处理、数据处理等耗时操作,提高程序的运行效率。 使用Python线程的主要步骤如下: 1. 导入threading模块。 ``` import threading ``` 2. 创建一个线程对象,可以通过继承threading.Thread类或使用threading.Thread()函数创建。 ``` class MyThread(threading.Thread): def __init__(self, name): super().__init__() self.name = name def run(self): # 线程执行的代码 print("Hello, " + self.name) thread1 = MyThread("Thread 1") thread2 = threading.Thread(target=func, args=("Thread 2",)) ``` 3. 启动线程。 ``` thread1.start() thread2.start() ``` 4. 等待线程结束。 ``` thread1.join() thread2.join() ``` 以上代码演示了两种创建多线程的方法:1)继承threading.Thread类,重写run方法;2)使用函数作为线程的执行内容。线程的启动调用start()方法,等待线程结束使用join()方法。 需要注意的是,Python线程的并发程度受到全局解释器锁(GIL)的限制,因此对于计算密集型的任务,多线程并不能发挥出多核的优势。如果需要发挥多核性能,可以考虑使用多进程编程。 总之,Python线程实例能够提高程序的并发处理能力,适用于需要同时处理多个任务的场景。通过合理设计线程的数量和任务分配,可以提高程序的性能和效率。 ### 回答3: Python线程实例是指通过使用线程的技术来提高Python程序的运行效率和性能。在Python中,我们可以使用threading模块来实现多线程。 多线程技术可以同时执行多个任务,提高程序的运行速度。在Python中,我们可以通过创建Thread对象并调用start()方法来启动一个线程。下面是一个简单的例子: import threading def print_numbers(): for i in range(1, 11): print(i) def print_letters(): for letter in ['A', 'B', 'C', 'D', 'E']: print(letter) # 创建两个线程 t1 = threading.Thread(target=print_numbers) t2 = threading.Thread(target=print_letters) # 启动两个线程 t1.start() t2.start() # 等待两个线程结束 t1.join() t2.join() # 主线程继续执行 print("主线程结束") 以上代码中,我们创建了两个线程,分别执行print_numbers()和print_letters()函数。通过调用start()方法启动线程,并通过join()方法等待两个线程执行完毕。最后,主线程继续执行并打印出一段文字。 需要注意的是,多线程并不一定能提高程序的运行速度,因为在Python中,全局解释器锁(Global Interpreter Lock,GIL)会限制同一时间只能有一个线程执行Python字节码。因此,在CPU密集型任务中,多线程并不能真正实现并行计算。但是,在IO密集型任务中,多线程能够提高程序的运行效率。 总结起来,Python的多线程实例可以通过使用threading模块来实现。多线程能够提高IO密集型任务的运行效率,但在CPU密集型任务中并不能真正实现并行计算。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值