1 线程的创建步骤

  1. 导入线程模块 import threading
  2. 通过线程类创建线程对象 threading_obj = threading.Thread(target=taskname)
  3. 启动线程 obj.start()

2 通过线程类创建线程对象

obj = threading.Thread(target=task_name)

参数名 说明
target 执行的目标任务名,这里指的是函数名(方法名)
name 进程名,一般不用设置
group 进程组,目前只能用None

3 线程创建与启动

  1. # 创建子线程
  2. sing_t = threading.Thread(target=sing,args=(3,'ck'),daemon=False)
  3. dance_t = threading.Thread(target=dance,args=(3,'ck'),daemon=False)
  4. sing_t.start()
  5. dance_t.start()

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

  1. @decorator_timer
  2. def work():
  3. for i in range(5):
  4. print(f'work..{i}')
  5. time.sleep(0.2)
  6. if __name__ == '__main__':
  7. # 创建子线程
  8. sub_t = threading.Thread(target=work)
  9. sub_t.start()
  10. time.sleep(0.5)
  11. print('main() has finished!')

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

  1. work..0
  2. work..1
  3. work..2
  4. main() has finished!
  5. work..3
  6. work..4
  7. work() has been running for "1.003s"...

设置守护主线程——主线程不需要等待子线程执行完成后再结束 daemon=True or sub_t.setDaemon(True)

sub_t = threading.Thread(target=work,daemon=True)
or
sub_t.setDaemon(True)
work..0
work..1
work..2
main() has finished!

Process finished with exit code 0

5 线程之间的执行顺序

1 线程之间的执行是无序的/CPU调度控制 无序

2 获取当前线程信息

# @decorator_timer
def task1():
    time.sleep(1)
    # current_thread 获取当前线程线程对象
    t_info = threading.current_thread()
    print(t_info)

@decorator_timer
def run():
    # 创建子线程
    for i in range(5):
        sub_t = threading.Thread(target=task1,daemon=False)
        sub_t.start()

下面输出结果可以看出运行无序

run() has been running for "0.001s"...
<Thread(Thread-2, started 11820)>
<Thread(Thread-1, started 22916)>
<Thread(Thread-4, started 24132)>
<Thread(Thread-3, started 16120)>
<Thread(Thread-5, started 15004)>

3 thread.join(timeout=None) 方法使线程有序

join()方法让线程直到终止前一直挂起;除非给了timeout参数,否则一直在队列中等待运行。在代码加入该语句。可以让线程在join()后续的代码执行前完成工作。这样就可以正确输出我们想要的程序运行总时间了。

文件夹高并发copy

# -*- coding:utf-8 -*-
# @Time  :   2020/9/2 10:38
# Author :   chgken
# @File  :   mulpro_copy.py
# @Software  :   PyCharm
import time
import timeit
import threading
import os
import functools

def decorator_timer(func):
    @functools.wraps(func)
    def wrapper(*args,**kwargs):
        t1 = timeit.default_timer()
        func(*args,**kwargs)
        t2 = timeit.default_timer()
        print(f'{func.__name__} has been running for "{round(t2-t1,3)}s..."')
        return func
    return wrapper


class MultiCopy():

    # 2. 读取源文件夹文件列表并多进程执行拷贝
    @decorator_timer
    def get_file_list(self,source_path ,destination_path):
        try:
            os.mkdir(destination_path)
        except:
            print('{self.destination_path} already existed!')
        file_lsit = os.listdir(source_path)
        # 3. 使用多进程实现多任务拷贝
        for file in file_lsit:
            sub_t = threading.Thread(target=self.copy_file, args=(file,source_path,destination_path,))
            sub_t.start()
    # 3. 使用多进程实现多任务拷贝
    @decorator_timer
    def copy_file(self,file,source_path ,destination_path):
        source_path = os.path.join(source_path,file)
        destination_path = os.path.join(destination_path,file)
        if os.path.isdir(source_path):
            print(f'redirecte to {source_path}')
            self.get_file_list(source_path,destination_path)
        else:
            with open(source_path,'rb') as sf:
                with open(destination_path,'wb') as df:
                    while True:
                        read_data = sf.read(1024)
                        if read_data:
                            df.write(read_data)
                        else:
                            print(f'{source_path} copy done!')
                            return


if __name__ == '__main__':
    # 1.定义目标文件夹和源文件夹地址
    source_path = r'E:\学院资料'
    destination_path = r'D:\桌面\学院资料_cp'
    run = MultiCopy()
    run.get_file_list(source_path,destination_path)