首页 > 其他分享 >线程的创建

线程的创建

时间:2024-01-18 20:11:51浏览次数:29  
标签:__ name url 创建 list 线程 print data

【一】threading模块介绍

  • 多线程创建和多进程创建很像
  • 我的理解是threading模块的作者遵循了鸭子类型
  • 所以和multiprocessing模块的使用方法那么像

【二】开启线程的两种方式

方式一

  • 直接调用 Thread 方法
from threading import Thread
import time


def task(name):
    print(f'{name}任务开始')
    time.sleep(2)
    print(f'{name}任务结束')


if __name__ == '__main__':
    t = Thread(target=task, args=('学习',))
    t.start()
    print('主线程')

方式二

  • 继承Thread类
from threading import Thread
import time


class MyThread(Thread):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def run(self) -> None:
        print(f'{self.name}任务开始')
        time.sleep(2)
        print(f'{self.name}任务结束')


if __name__ == '__main__':
    t = MyThread(name='打篮球')
    t.start()
    print('主线程')
  • 用法基本和multiprocessing模块,也就是创建进程的方式一模一样

【三】查看ID

  • 用threading模块里面的current_thread方法
from threading import Thread,current_thread
import time


def task(name):
    print(f'{name}任务开始')
    print(current_thread().native_id)
    time.sleep(2)
    print(f'{name}任务结束')


if __name__ == '__main__':
    t = Thread(target=task, args=('学习',))
    t.start()
    print('主线程')
  • 用os模块里面的getpid()方法
from threading import Thread
import time
from os import getpid

def task(name):
    print(f'{name}任务开始')
    print(getpid())
    time.sleep(2)
    print(f'{name}任务结束')


if __name__ == '__main__':
    t = Thread(target=task, args=('学习',))
    t.start()
    print('主线程')

【四】多线程并发的socket服务端

  • 服务端
from threading import Thread
import socket
from socket import SOL_SOCKET, SO_REUSEADDR

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
server.bind(('127.0.0.1', 8080))
server.listen(5)


def talk(conn):
    while True:
        try:
            msg = conn.recv(1024).decode('utf-8')
            print(f'客户端:>>>>{msg}')

            conn.send(msg.upper().encode('utf-8'))
        except Exception as error:
            print(error)
            break
    conn.close()


def threading_version(conn):
    t = Thread(target=talk, args=(conn,))
    t.start()


def main_threading():
    while True:
        conn, addr = server.accept()
        threading_version(conn=conn)


if __name__ == '__main__':
    main_threading()

  • 客户端(不变)
from socket import *

# 不写参数:默认是TCP协议
# (1)创建客户端对象
client = socket()

# (2)绑定 IP PORT
# (2)建立链接桥梁 --(呼应客户端的 ip 和 port)
IP = '127.0.0.1'
PORT = 8080
client.connect((IP, PORT))

# (4)链接循环
while True:
    # (4.1)向服务端发数据
    msg_to_server = input('请输入消息:>>>>').strip()

    if not msg_to_server:
        continue
    client.send(msg_to_server.encode('utf-8'))

    # 接受服务器返回的数据
    data_from_server = client.recv(1024)
    print(data_from_server.decode('utf-8'))
    if msg_to_server == 'q':
        break
client.close()

【五】单进程,多进程,多线程速度比较

  • 通过一个爬虫案例
import requests
import os
import time
from lxml import etree
from multiprocessing import Process
from threading import Thread


def timer(func):
    def inner(*args, **kwargs):
        start_time = time.time()
        func(*args, **kwargs)
        print(f'总耗时{time.time() - start_time}秒')

    return inner


def create_url_list():
    url_list = []
    for i in range(1, 6):
        if i == 1:
            url = 'https://pic.netbian.com/4kmeinv/'
            url_list.append(url)
        else:
            url = f'https://pic.netbian.com/4kmeinv/index_{i}.html'
            url_list.append(url)
    return url_list


def spider_data(url_list):
    data_dic = []
    for url in url_list:
        response = requests.get(url=url)
        response.encoding = 'gbk'
        response_text = response.text

        html_obj = etree.HTML(response_text)
        li_list = html_obj.xpath('//*[@id="main"]/div[3]/ul/li')

        for li in li_list:
            src = "https://pic.netbian.com/" + li.xpath('./a/img/@src')[0]
            title = li.xpath('./a/b/text()')[0]
            data_dic.append({'src': src, 'title': title})
    return data_dic


def save_data(file_title, file_src):
    file_name = 'image'
    file_path = os.path.join(os.path.dirname(__file__), file_name)
    os.makedirs(file_path, exist_ok=True)
    file_path = os.path.join(file_path, f'{file_title}.png')
    data = requests.get(file_src)
    with open(file_path, 'wb') as fp:
        fp.write(data.content)
    print(f'当前图片{file_title}保存完成')


@timer
def main_normal():
    url_list = create_url_list()
    data_list = spider_data(url_list=url_list)
    for data in data_list:
        image_src = data.get('src')
        image_title = data.get('title')
        save_data(image_title, image_src)


@timer
def main_process():
    url_list = create_url_list()
    data_list = spider_data(url_list=url_list)
    p_list = []
    for data in data_list:
        image_src = data.get('src')
        image_title = data.get('title')
        p = Process(target=save_data, args=(image_title, image_src))
        p.start()
        p_list.append(p)
    for p in p_list:
        p.join()


@timer
def main_thread():
    url_list = create_url_list()
    data_list = spider_data(url_list=url_list)
    p_list = []
    for data in data_list:
        image_src = data.get('src')
        image_title = data.get('title')
        p = Thread(target=save_data, args=(image_title, image_src))
        p.start()
        p_list.append(p)
    for p in p_list:
        p.join()


if __name__ == '__main__':
    ...
# main_normal() 34s
# main_process() 9.7s
# main_thread()  7s

  • 可以看到在多IO阻塞时的速度比较结果为
  • 多线程>多进程>单进程

标签:__,name,url,创建,list,线程,print,data
From: https://www.cnblogs.com/Hqqqq/p/17973295

相关文章

  • 对线程的理解
    【一】什么是线程线程可以被看作是在程序内部的一个独立的任务流,它是操作系统能够进行运算调度的最小单位。线程存在于进程之中,可以把进程想象成一个工厂,而线程就像是工厂里的工人。想象你有一个工厂(这个工厂就像一个进程),在这个工厂里有很多工人(这些工人就是线程)。这些工人......
  • 进程线程关系
    1、什么是进程什么是进程呢?进程是程序的一次启动执行。什么是程序呢?程序是存放在硬盘中的可执行文件,主要包括代码指令和数据。一个进程是一个程序的一次启动和执行,是操作系统将程序装入内存,给程序分配必要的系统资源,并且开始运行程序的指令。进程与程序是什么关系呢?同一......
  • Electron 创建项目
    前言项目创建electron项目,参考官网的文档来,我也只是入门哈哈哈官网https://electronjs.p2hp.com/docs/latest/tutorial/tutorial-first-app1.创建一个文件夹electron-app然后cd electron-app这个目录下npminit然后加上 "start":"electron.",这句命令......
  • C++多线程
    C++多线程的语法以及使用1.线程的创建首先创建一个多线程入口函数threadmain,threadmain函数体中完成子线程所要做的事。接着在主函数中创建线程对象th,调用构造函数,并传递一个函数指针作为入口函数:threadth(treadmain);入口函数为thread构造函数的参数。之后在主线程中......
  • StringBuilder 线程不安全,到底哪里不安全?
    StringBuilder线程不安全,到底哪里不安全?在Java中,字符串拼接是一个非常常见的操作,而对于频繁变动的字符串内容,使用StringBuilder是一个性能优化的选择。但是,StringBuilder在使用上存在一个很大的限制,它是线程不安全的。在多线程环境下,不正确的使用StringBuilder可能导致数据不一......
  • 【OC】一份理解引用计数、runloop、子线程保活比较好的调试代码
    以下提供了一份ViewController.m的源代码,调试工程可以做成:AppDelegate.rootViewController=NavivationController(rootController:rootVC)然后再rootVC中点击屏幕,self.navigationControllerpush:viewController,然后就可以调试代码进行理解。#import"ViewController.h"......
  • python创建httpserver,并处理get、post请求
    搭建一个简单的httpserver,用于测试数据通讯fromhttp.serverimportHTTPServer,BaseHTTPRequestHandlerimportjsondata={'result':'thisisatest'}host=('localhost',8888)classResquest(BaseHTTPRequestHandler):  defdo_GET(self):   ......
  • 解决虚拟机环境下使用Ubuntu自带的图形化工具创建的磁盘分区无法扩容的问题
    解决虚拟机环境下使用Ubuntu自带的图形化工具创建的磁盘分区无法扩容的问题先来个结论:不要使用Ubuntu自带的图形化磁盘工具创建分区,磁盘分区操作请使用fdisk等工具。正文太长不想看的记住这个结论就行,有兴趣的接着看。首先介绍一下磁盘的基本配置,vmware中创建了两块磁盘,一......
  • 不创建临时变量求字符串长度--初识递归
    递归:一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法。递归的例题应用:不创建临时变量求字符串长度。intmy_strlen(char*str){ if(*str!='\0') { return1+my_strlen(str+1); } else return0;}intmain(){ chararr[]="bi......
  • Git必知必会基础(06):分支创建、切换、更新、删除、拉取
     本系列汇总,请查看这里:https://www.cnblogs.com/uncleyong/p/10854115.html 简介分支就是版本上的更新送代,默认只有master主分支可以从主分支上分离出其他的分支,各分支间互不干扰每个项目,一般有多个分支,比如master(主干分支)、开发分支、测试分支、生产bug分支等等线上环境,......