Python多线程编程深度探索:从入门到实战

news2024/11/15 21:26:31

title: Python多线程编程深度探索:从入门到实战
date: 2024/4/28 18:57:17
updated: 2024/4/28 18:57:17
categories:

  • 后端开发

tags:

  • 多线程
  • 并发编程
  • 线程安全
  • Python
  • 异步IO
  • 性能优化
  • 实战项目

在这里插入图片描述

第1章:Python基础知识与多线程概念

Python简介:

Python是一种高级、通用、解释型的编程语言,由Guido van Rossum于1991年创建。Python以其简洁、易读的语法而闻名,被广泛用于Web开发、数据科学、人工智能等领域。Python具有丰富的标准库和第三方库,支持多种编程范式,包括面向对象、函数式和过程式编程。

线程与进程的区别:

  • 进程(Process)是操作系统分配资源的基本单位,每个进程有独立的内存空间,进程之间相互独立。
  • 线程(Thread)是进程内的执行单元,一个进程可以包含多个线程,它们共享进程的内存空间和资源。
  • 线程比进程更轻量级,创建和销毁线程的开销较小,线程间的切换速度也更快。
  • 多线程编程通常用于提高程序的并发性和效率,但也需要注意线程安全和同步的问题。

Python中的线程支持:

Python标准库中的threading模块提供了对线程的支持,使得在Python中可以方便地创建和管理线程。threading模块提供了Thread类用于创建线程对象,通过继承Thread类并重写run()方法可以定义线程的执行逻辑。除了基本的线程操作外,threading模块还提供了锁、事件、条件变量等同步工具,帮助开发者处理线程间的同步和通信问题。在Python中,由于全局解释器锁(GIL)的存在,多线程并不能实现真正意义上的并行执行,但可以用于处理I/O密集型任务和提高程序的响应速度。

第2章:Python多线程基础

创建线程:threading模块

在Python中,我们可以使用threading模块来创建和管理线程。主要步骤如下:

  1. 导入threading模块
  2. 定义一个继承自threading.Thread的子类,并重写run()方法来实现线程的执行逻辑
  3. 创建该子类的实例,并调用start()方法启动线程

示例代码:

import threading

class MyThread(threading.Thread):
    def run(self):
        # 线程执行的逻辑
        print("This is a new thread.")

# 创建线程实例并启动
t = MyThread()
t.start()

线程生命周期

线程有以下几种状态:

  • 初始状态(New):线程对象已创建,但还未启动
  • 就绪状态(Runnable):线程已启动,正在等待CPU时间片
  • 运行状态(Running):线程获得CPU时间片并正在执行
  • 阻塞状态(Blocked):线程由于某种原因放弃CPU时间片,暂时无法运行
  • 终止状态(Terminated):线程已经结束执行

线程在这些状态之间转换,直到最终进入终止状态。

线程同步与通信

由于线程共享进程的资源,因此需要使用同步机制来协调线程的访问,避免出现数据竞争和不一致的问题。threading模块提供了以下同步工具:

  1. Lock:互斥锁,用于保护临界区资源
  2. RLock:可重入锁,允许同一线程多次获取锁
  3. Condition:条件变量,用于线程间的通知和等待
  4. Semaphore:信号量,控制对共享资源的访问数量
  5. Event:事件对象,用于线程间的事件通知

第3章:线程池与异步编程

ThreadPoolExecutor

ThreadPoolExecutor是Python中的线程池实现,位于concurrent.futures模块中,可以方便地管理多个线程来执行并发任务。主要特点包括:

  • 提供了submit()方法来提交任务给线程池执行
  • 可以控制线程池的大小,避免创建过多线程导致资源浪费
  • 支持异步获取任务执行结果

示例代码:

from concurrent.futures import ThreadPoolExecutor

def task(n):
    return n * n

# 创建线程池
with ThreadPoolExecutor(max_workers=3) as executor:
    # 提交任务
    future = executor.submit(task, 5)
    # 获取任务结果
    result = future.result()
    print(result)

Asynchronous I/O与协程

异步I/O是一种非阻塞的I/O模型,通过事件循环在I/O操作完成前不断切换执行任务,提高程序的并发性能。Python中的协程是一种轻量级的线程,可以在遇到I/O操作时主动让出CPU,让其他任务执行。

asyncio模块简介

asyncio是Python标准库中用于编写异步I/O的模块,基于事件循环和协程的概念,提供了高效的异步编程解决方案。主要组成部分包括:

  • 事件循环(Event Loop):负责调度协程任务的执行
  • 协程(Coroutines):使用asyncawait关键字定义的异步任务
  • Future对象:表示异步操作的结果,可用于获取任务执行状态和结果
  • 异步I/O操作:通过asyncio提供的异步API实现非阻塞I/O操作

示例代码:

import asyncio

async def main():
    print("Hello")
    await asyncio.sleep(1)
    print("World")

# 创建事件循环并运行协程
asyncio.run(main())

总结:线程池和异步编程是Python中处理并发任务的重要技术,能够提高程序的性能和效率。通过ThreadPoolExecutor管理线程池,以及利用asyncio模块实现异步I/O和协程,可以编写出高效且响应迅速的异步程序。

第4章:线程同步技术

Locks和RLocks

  • Locks(简单锁):threading.Lock是互斥锁,用于保护共享资源,确保在一个时间只有一个线程可以访问。当一个线程获取到锁后,其他线程必须等待该锁释放。
import threading

lock = threading.Lock()

def thread_function():
    with lock:
        print("Thread is executing")
  • RLocks(可重入锁,Reentrant Locks):threading.RLock允许在已经获取锁的线程中再次获取,但不能在其他线程中获取。这在需要在循环内部获取锁的场景中很有用。
rlock = threading.RLock()
for _ in range(5):
    rlock.acquire()
    # do something
    rlock.release()

Semaphores

  • Semaphores(信号量):threading.Semaphore用于控制同时访问资源的线程数量。它维护一个计数器,当计数器大于0时,线程可以获取,计数器减一;当计数器为0时,线程必须等待。
semaphore = threading.Semaphore(3)

def thread_function():
    semaphore.acquire()
    try:
        # do something
    finally:
        semaphore.release()

Conditions and Events

  • Conditions(条件变量):threading.Condition用于线程之间的通信,允许线程在满足特定条件时进入或退出等待状态。它通常与锁一起使用。
lock = threading.Lock()
cond = threading.Condition(lock)

def thread1():
    cond.acquire()
    try:
        # wait for condition
        cond.wait()
        # do something
    finally:
        cond.release()

def thread2():
    with lock:
        # set condition
        cond.notify_all()
  • Events(事件):threading.Event也用于线程间的通信,但它只是标志,可以被设置或清除。当设置后,所有等待的线程都会被唤醒。
event = threading.Event()

def thread1():
    event.wait()  # 等待事件
    # do something
event.set()  # 设置事件,唤醒等待的线程

Queues和Priority Queues

  • Queues(队列):queue模块提供了多种队列实现,如QueuePriorityQueue等。Queue是FIFO(先进先出)队列,PriorityQueue是优先级队列,按照元素的优先级进行排序。
import queue

q = queue.Queue()
q.put('A')
q.put('B')
q.get()  # 返回'A'
q.put('C', block=False)  # 如果队列满,不阻塞,直接抛出异常

# 使用PriorityQueue
pq = queue.PriorityQueue()
pq.put((3, 'C'))
pq.put((1, 'A'))
pq.get()  # 返回('A', 1)

这些同步工具帮助管理线程间的交互,确保资源安全和并发控制。在并发编程中,正确使用这些技术是避免竞态条件和死锁的关键。

第5章:线程间的通信与数据共享

Shared Memory

  • 共享内存是线程间通信的一种方式。Python中可以使用multiprocessing模块中的ValueArray来创建共享内存对象。
from multiprocessing import Value, Array

def worker(counter, array):
    with counter.get_lock():
        counter.value += 1
    array[0] += 1

if __:
    counter = Value('i', 0)  # 'i'表示整型
    array = Array('i', 3)  # 长度为3的整型数组
    # 多个线程可以访问counter和array

Pickle和Queue模块

  • Pickle模块可以将Python对象序列化为字节流,在线程间传递。
  • Queue模块提供了线程安全的队列实现,可以用于线程间通信。
import pickle
from queue import Queue

q = Queue()
obj = {'a': 1, 'b': 2}
q.put(pickle.dumps(obj))
received_obj = pickle.loads(q.get())

threading.local

  • threading.local可以为每个线程创建独立的数据副本。这对于需要在线程间共享数据但又不希望产生竞争条件的情况很有用。
import threading

local_data = threading.local()

def worker():
    local_data.x = 123
    print(f"Thread {threading.current_thread().name}: {local_data.x}")

if __:
    t1 = threading.Thread(target=worker)
    t2 = threading.Thread(target=worker)
    t1.start()
    t2.start()
    t1.join()
    t2.join()

这些通信和共享技术可以帮助我们在多线程环境中更好地管理数据和状态。合理使用这些工具可以提高程序的并发性和健壮性。

第6章:线程安全与并发编程最佳实践

避免全局变量的使用

  • 全局变量在多线程环境下容易产生竞争条件和线程安全问题。
  • 应尽量使用局部变量或将共享数据封装到对象中。如果必须使用全局变量,要对其进行加锁保护。

避免死锁

  • 死锁是多线程编程中常见的问题。产生死锁的主要原因包括:

    1. 循环等待资源
    2. 资源占用和请求不当
    3. 资源分配策略不当
  • 预防死锁的措施包括:

    1. 合理设计资源分配策略
    2. 使用顺序加锁
    3. 使用超时机制
    4. 使用threading.RLock支持重入

使用线程池的注意事项

  • 线程池可以帮助管理线程的创建和销毁,提高性能。但使用时需注意:

    1. 线程池大小设置要合理,既不能过小影响并发度,也不能过大耗费资源
    2. 任务提交要合理安排,避免短时间内大量任务堆积
    3. 合理设置任务超时时间,避免无法响应的任务阻塞线程池
    4. 监控线程池健康状态,及时处理异常情况

第7章:并发编程实战项目

网络爬虫并发处理

  • 网络爬虫是常见的并发编程应用场景。可以使用多线程技术并发处理多个URL,提高爬取速度。

    1. 使用线程池管理工作线程,提交爬取任务。
    2. 使用concurrent.futures模块提交I/O密集型任务。
    3. 使用queue.Queuecollections.deque管理URL队列,避免爬取重复页面。
    4. 使用threading.Semaphore限制并发数量,避免爬取速度过快被服务器拒绝。

数据分析任务并行处理

  • 数据分析任务也可以使用多线程技术提高处理速度。

    1. 使用concurrent.futures模块提交CPU密集型任务。
    2. 使用multiprocessing模块提交CPU密集型任务,避免GIL的限制。
    3. 使用Pool.mapPool.starmap分发数据,使用Pool.applyPool.apply_async分发函数。
    4. 使用concurrent.futures模块的ThreadPoolExecutorProcessPoolExecutor两种模式,选择适合的并发模型。

GUI应用中的多线程

  • GUI应用中使用多线程需要注意:

    1. GUI线程必须独立,不能被其他线程阻塞。
    2. 数据共享需要使用队列或管道,避免直接修改GUI控件。
    3. 使用threading.Eventthreading.Condition实现线程间通信。
    4. 使用QThreadQRunnable等Qt提供的多线程工具。

总之,在实际项目中,需要根据具体情况合理使用并发编程技术,提高系统性能和效率。同时,需要注意线程安全和可维护性问题,避免过度使用多线程带来的复杂性。

第8章:多线程在分布式系统中的应用

远程过程调用(RPC, Remote Procedure Call)

  • RPC是一种允许分布式系统中的应用进程之间互相调用对方的程序功能的技术。

    • 使用多线程的RPC可以实现:

      • 在服务器端,每个处理线程处理客户端的请求,提高并发能力。
      • 在客户端,发起请求和接收回应可以异步进行,提高响应速度。
      • 使用如gRPCSOAPRESTful API等技术实现,如gRPC使用protobuf定义服务和消息,threadingasyncio处理请求。

Socket多线程服务器实现

  • Socket多线程服务器是分布式系统中常见的服务器架构,适用于网络通信场景。

  • 实现步骤:

    1. 创建一个主线程,监听指定的端口,接受客户端连接。
    2. 使用socket.accept()创建新的子线程(客户端连接)。
    3. 每个子线程(服务器端)创建一个单独的线程处理客户端请求,如读取数据、发送数据,可以使用socket.recv()socket.send()
    4. 确保子线程在完成任务后正确关闭连接,如使用socket.close()
    5. 使用threading.Threadasynciostart_server函数来实现多线程服务。
import socket
import threading

def handle_client(client_socket):
    request = client_socket.recv(1024)
    # 处理请求
    response = "Hello, Client!"
    client_socket.send(response.encode())
    client_socket.close()

def server_thread(host, port):
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind((host, port))
    server_socket.listen(5)

    while True:
        client, addr = server_socket.accept()
        client_handler = threading.Thread(target=handle_client, args=(client,))
        client_handler.start()

if __name__ == "__main__":
    server_thread('localhost', 12345)

这个例子展示了如何创建一个基本的Socket多线程服务器。在实际项目中,可能还需要处理异常、连接管理、负载均衡等复杂情况。

第9章:线程安全的并发数据结构

在多线程编程中,使用线程安全的数据结构可以确保在多个线程中进行读写操作时不会发生竞争条件和数据不一致。

  • collections.deque: 一个线程安全的双端队列,可以用于多线程环境下的队列操作。
  • queue.Queue: 一个基于锁的队列,可以用于多线程环境下的生产者-消费者模型。
  • threading.Semaphore: 一个计数信号量,可以用于对有限资源进行访问控制。
  • threading.Lock: 一个基本的互斥锁,可以用于对共享资源进行访问控制。
  • threading.RLock: 一个可重入的互斥锁,可以用于对共享资源进行访问控制。

concurrent.futures模块

  • concurrent.futures 是一个高级并发库,提供了一种简单的方式来使用多线程和多进程。
  • ThreadPoolExecutor: 一个基于线程池的执行器,可以用于在多线程中执行任务。
  • ProcessPoolExecutor: 一个基于进程池的执行器,可以用于在多进程中执行任务。
  • Future: 一个可以在未来返回结果的对象,可以用于在多线程和多进程中执行任务。

threading.local的高级应用

  • threading.local: 一个线程本地存储对象,可以用于在多线程中保存线程特定的数据。
  • 高级应用:可以用于在多线程中实现线程隔离的数据库连接池。
import threading

class ThreadLocalDBConnection:
    _instances = {}

    def __init__(self, db_name):
        self.db_name = db_name

    def __enter__(self):
        if self.db_name not in self._instances:
            self._instances[self.db_name] = threading.local()
        self._instances[self.db_name].conn = create_connection(self.db_name)
        return self._instances[self.db_name].conn

    def __exit__(self, exc_type, exc_val, exc_tb):
        self._instances[self.db_name].conn.close()

# 使用
with ThreadLocalDBConnection('db1') as conn:
    # 在当前线程中使用conn

这个例子展示了如何使用threading.local实现一个线程隔离的数据库连接池。在多线程中使用它,可以确保每个线程都有自己的连接,而不会发生竞争条件。

第10章:性能调优与线程管理

线程性能瓶颈分析

  • CPU密集型:当程序的瓶颈在CPU上时,可以通过使用多线程或多进程来提高性能。
  • I/O密集型:当程序的瓶颈在I/O上时,可以使用多线程来提高性能。
  • 锁竞争:当多个线程在争抢同一个锁时,可能会导致性能瓶颈。
  • 死锁:当多个线程因争抢资源而导致死锁时,可能会导致性能瓶颈。

线程池大小的优化

  • 线程数量与CPU核心数量相等:在CPU密集型的程序中,可以将线程数量设为CPU核心数量。
  • 线程数量与CPU核心数量的两倍:在I/O密集型的程序中,可以将线程数量设为CPU核心数量的两倍。
  • 线程数量与系统资源有关:在系统资源有限的情况下,可以适当减小线程数量。

线程生命周期管理

  • 线程创建:创建一个线程需要消耗一定的系统资源。
  • 线程启动:启动一个线程需要消耗一定的系统资源。
  • 线程运行:线程运行期间需要消耗CPU资源。
  • 线程结束:结束一个线程需要消耗一定的系统资源。

在管理线程生命周期时,可以采用如下策略:

  • 预先创建线程:在程序启动时,预先创建一定数量的线程,并将它们放入线程池中。
  • 按需创建线程:在程序运行时,按需创建线程,并将它们放入线程池中。
  • 限制线程数量:在程序运行时,限制线程数量,避免创建过多的线程导致系统资源不足。
import threading
import time

class MyThread(threading.Thread):
    def run(self):
        time.sleep(1)

# 预先创建线程
thread_pool = [MyThread() for _ in range(10)]
for thread in thread_pool:
    thread.start()
for thread in thread_pool:
    thread.join()

# 按需创建线程
while True:
    if condition:
        thread = MyThread()
        thread.start()
        thread.join()

# 限制线程数量
thread_pool = []
for _ in range(10):
    thread = MyThread()
    thread.start()
    thread_pool.append(thread)
for thread in thread_pool:
    thread.join()

这些例子展示了如何在程序中管理线程的生命周期。可以根据实际需求来选择适合的策略。

第11章:现代Python并发框架:asyncio和AIOHTTP

异步编程的未来

  • Python 3.5引入了asyncio库,标志着Python开始支持异步/协程编程,这是一种处理I/O密集型任务的高效方式,尤其是在网络编程中。

  • 异步编程在未来的发展趋势:

    • 更广泛的应用:随着服务器端和客户端编程的不断发展,异步编程将越来越重要,特别是在Web开发、网络服务、游戏开发等领域。
    • 更好的性能:异步编程可以显著减少阻塞,提高程序的并发处理能力。
    • 异步/并行混合:现代编程可能更多地采用异步I/O与并行计算的结合,以充分利用多核处理器和网络资源。

AIOHTTP库简介

  • AIOHTTP(Asynchronous I/O HTTP Client/Server)是一个基于asyncio的高性能Python HTTP客户端和服务器库。
  • 它的设计目标是提供一个易于使用的API,同时保持高性能和可扩展性,特别适合用于构建异步的Web服务和API。
  • AIOHTTP支持HTTP/1.1和HTTP/2协议,支持连接池、请求/响应缓存、自动重试、流处理、WebSocket等特性。
  • 使用AIOHTTP,开发者可以编写更简洁、高效的网络代码,减少阻塞,提高并发处理能力。

以下是一个简单的AIOHTTP示例,用于发送GET请求:

import asyncio
import aiohttp

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    async with aiohttp.ClientSession() as session:
        html = await fetch(session, 'https://example.com')
        print(html)

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

在这个例子中,fetch函数是一个协程,使用aiohttp.ClientSession的异步上下文管理器来发起GET请求。main函数也是协程,使用run_until_complete来调度和运行协程。

AIOHTTP的使用可以帮助你构建更现代、高效的网络应用,尤其是在处理大量并发请求时。

第12章:实战案例与项目搭建

实战案例分析

在实际应用中,我们可能需要使用多线程爬虫来抓取大量数据,并对其进行实时分析。这种应用场景可以帮助我们理解如何使用多线程技术与数据分析工具来构建一个高效的数据处理系统。

项目实战:多线程爬虫与实时分析

这个项目将包括以下步骤:

  1. 确定爬取目标:首先,我们需要确定我们想要爬取的数据。在这个例子中,我们选择爬取一些新闻网站的文章标题和摘要。
  2. 设计数据结构:我们需要设计一个数据结构来存储爬取到的数据。可以使用一个Python字典,包括以下属性:titlesummaryurl
  3. 实现多线程爬虫:我们可以使用concurrent.futures库中的ThreadPoolExecutor来实现多线程爬虫。每个线程负责爬取一个网站,并将数据存入一个共享的队列中。
  4. 实现实时分析:我们可以使用pandas库来实现数据分析。每当爬虫从队列中取出一个新的数据项时,我们可以将其添加到一个pandas.DataFrame中,并进行实时分析。

以下是一个简化版的示例代码:

import requests
from bs4 import BeautifulSoup
import concurrent.futures
import pandas as pd

# 定义爬取函数
def fetch(url):
    response = requests.get(url)
    soup = BeautifulSoup(response.text, 'html.parser')
    title = soup.find('h1').text
    summary = soup.find('p').text
    return {'title': title, 'summary': summary, 'url': url}

# 定义线程池
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
    # 提交爬取任务
    urls = ['https://www.example1.com', 'https://www.example2.com', 'https://www.example3.com']
    futures = [executor.submit(fetch, url) for url in urls]

    # 获取爬取结果
    data = []
    for future in concurrent.futures.as_completed(futures):
        result = future.result()
        data.append(result)

# 实现实时分析
df = pd.DataFrame(data)
print(df)

在这个示例代码中,我们使用ThreadPoolExecutor来创建一个五个线程的线程池,并提交三个爬取任务。每个爬取任务负责爬取一个网站,并将数据存入一个列表中。最后,我们将列表转换为一个pandas.DataFrame,并进行实时分析。

注意,这个示例代码仅供参考,并且可能需要进行修改和优化,以适应实际应用场景。

附录:工具与资源

个人页面-爱漫画

相关Python库介绍

  1. requests:用于发送HTTP请求,获取网页内容。
  2. BeautifulSoup:用于解析HTML和XML文档,方便提取数据。
  3. concurrent.futures:Python标准库,提供多线程和多进程的并发执行框架,如ThreadPoolExecutorProcessPoolExecutor
  4. pandas:强大的数据处理库,可以进行数据清洗、转换、分析等操作。
  5. threading:Python的内置库,提供线程的基本操作。
  6. time:用于时间操作,如设置线程等待时间。
  7. logging:用于日志记录,便于调试。

测试与调试工具

  1. pytest:Python的测试框架,用于编写和运行测试用例。
  2. pdb:Python的内置调试器,用于单步执行代码和检查变量值。
  3. PyCharmVS Code:集成开发环境(IDE),有强大的调试功能。
  4. Postmancurl:用于测试HTTP请求,确认爬虫是否正确工作。

高级并发编程书籍推荐

  1. 《Python并发编程实战》(Fluent Python Concurrency) :作者是Luciano Ramalho,深入讲解了Python的并发编程,包括多线程、多进程、协程和异步I/O等。
  2. 《Concurrent Programming in Python》(Python并发编程) :作者是David Beazley和Brian K. Jones,详细介绍了Python的并发编程技术。
  3. 《Python Cookbook》(Python编程:从入门到实践) :其中包含了一些高级并发编程的实用技巧和示例。
  4. 《The Art of Multiprocessing》(多线程编程艺术) :虽然不是专门针对Python,但其原理和策略对理解Python并发编程有帮助。

阅读这些书籍或教程,可以帮助你更好地理解和掌握Python中的并发编程,以及如何有效地进行测试和调试。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1630779.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

WPF 6 命令

命令 创建一个按钮,新建一个事件,按住F12 就可以添加业务代码 运行代码 此时希望UI与后台代码分离,互不影响 此时新建一个MainViewModel类,来保存业务代码 Icommand 是所有command的父类接口 新建一个command来实现这个接口…

怎么才能让数字在横线上缩小了数字还在横线上

<!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>刻度</title> </head> <style typ…

遇到软件测试职业瓶颈,如何突破

作为职场人&#xff0c;遇到发展瓶颈是在所难免的&#xff0c;无论是晋升受限、技能升级缓慢&#xff0c;还是工作激情的丢失&#xff0c;这些挑战都可能让人感到挫败。但是&#xff0c;积极应对&#xff0c;你就可能找到那扇通向新机遇的窗。 1. 自我评估 识别问题 是缺乏技…

武汉星起航:挂牌上海股权中心,开启资本新篇章助力跨境电商飞跃

2023年10月30日&#xff0c;武汉星起航电子商务有限公司在上海股权托管交易中心成功挂牌展示&#xff0c;标志着这家在跨境电商领域拥有卓越声誉的企业正式迈入了资本市场的大门。对于武汉星起航来说&#xff0c;这不仅是其发展历程中的一个重要里程碑&#xff0c;更是对其业务…

<计算机网络自顶向下> Internet Protocol(未完成)

互联网中的网络层 IP数据报格式 ver: 四个比特的版本号&#xff08;IPV4 0100, IPV6 0110&#xff09; headlen&#xff1a;head的长度&#xff08;头部长度字段&#xff08;IHL&#xff09;指定了头部的长度&#xff0c;以32位字&#xff08;4字节&#xff09;为单位计算。这…

mysql 开启远程连接

登录到mysql mysql -uroot -p 打开mysql数据库并查询user表 use mysql; select user, host from user;更改需要远程连接数据库为任何ip 可以连接&#xff0c; 并刷新系统权限相关的表 update user set host% where hostlocalhost and userroot; flush privileges;

算法课程笔记——如何倍增

快速幂 读入量大于1e5不要用cin读入&#xff0c;要用也要关闭同步流 第i个o次方的父亲 #include<bits/stdc.h>usingnamespacestd; #definemaxn 110000#definell long longintn, a[maxn], f[maxn][40]; intquery(intl, intr){intk (int)(log((r - l 1) * 1.0) / log(2.0…

第3篇:创建Nios II工程之Hello_World<二>

Q&#xff1a;上一期介绍完基本设计流程和实验原理&#xff0c;接着我们完成系统硬件设计部分&#xff0c;包括Platform Designer系统及Quartus工程。 A&#xff1a;依次搜索并添加Nios II Processor、JTAG UART、On-Chip Memory和System ID IP组件&#xff0c;连接各组件并As…

扫码分享文件效果怎么做?文件转换成二维码的教程

文件如何快速分享并通过手机查看呢&#xff1f;传统方式一般会通过微信、QQ或者网盘的方式来分享在线内容&#xff0c;但是这种方式需要占用获取内容者的存储空间&#xff0c;所以很多人现在会通过文件转二维码的方式&#xff0c;将二维码分享后通过扫码来获取文件内容。这种方…

Java 基于Graphics2D 实现海报(支持自定义颜色,背景,logo,贴图)

效果&#xff1a; 海报一&#xff1a; 海报二&#xff1a; 代码&#xff1a; 参数实体类&#xff1a; package com.ly.cloud.dto;import lombok.Data;/*** Author * Date Created in 2024/4/24 下午2:16* DESCRIPTION: 海报页面所需的参数 实体类* Version V1.0*/ Dat…

防火墙对要保护的服务器做端口映射的好处是几个

防火墙对要保护的服务器进行端口映射具有多重好处&#xff0c;这些好处主要围绕网络安全性、灵活性和可管理性展开。以下是对这些好处的专业分析&#xff1a; 1. 增强网络安全性&#xff1a;端口映射允许防火墙对进入服务器的流量进行精确控制。通过映射特定端口&#xff0c;防…

volatile的相关知识点

volatitle这个关键字&#xff0c;不管是在Java还是在C中都有使用到&#xff0c;但是在两种语言中&#xff0c;由于编译器的原因&#xff0c;他们存在一点点区别。 C中的volatile关键字 在C中volatile主要用于告诉编译器&#xff0c;这个变量的值可能会意外改变 ,例如被硬件或者…

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之七 简单进行人脸检测并添加面具特效实现

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之七 简单进行人脸检测并添加面具特效实现 目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之七 简单进行人脸检测并添加面具特效实现 一、简单介绍 二、简单进行…

ChatGPT记忆功能终于上线了, OpenAI 官方:用得越久越聪明!

原文 ChatGPT记忆功能终于上线了, OpenAI 官方&#xff1a;用得越久越聪明&#xff01; Aitrainee | 公众号&#xff1a;AI进修生 &#x1f31f; 记得今年2月份OpenAI发布过ChatGPT上线记忆功能的消息&#xff0c;我记得当时还弹出过这个窗口给我&#xff0c;但是仅仅体验了几…

centos7 openresty lua 自适应webp和缩放图片

目录 背景效果图准备安装cwebp等命令&#xff0c;转换文件格式安装ImageMagick&#xff0c;压缩文件下载Lua API 操控ImageMagick的依赖包 代码参考 背景 缩小图片体积&#xff0c;提升加载速度&#xff0c;节省流量。 效果图 参数格式 &#xff1a; ?image_processformat,…

C语言之详细讲解文件操作

什么是文件 与普通文件载体不同&#xff0c;文件是以硬盘为载体存储在计算机上的信息集合&#xff0c;文件可以是文本文档、图片、程序等等。文件通常具有点三个字母的文件扩展名&#xff0c;用于指示文件类型&#xff08;例如&#xff0c;图片文件常常以KPEG格式保存并且文件…

idea创建完项目如何隐藏不重要的文件

如果您不打算直接使用这些脚本&#xff0c;而是更倾向于通过IDEA的内置工具来运行Maven命令&#xff0c;那么您可以选择隐藏这些文件。但是&#xff0c;隐藏这些文件并不会影响它们的功能&#xff0c;只是在项目视图中不再显示它们。 1.转到 File > Settings&#xff08;Wi…

信息系统项目管理师——第7章项目立项管理

本章考选择题2-3分&#xff0c;案例和论文均有可能作为领域考试。 项目建议与立项申请♥♥♥♥♥ 立项申请的概念 立项申请又称为项目建议书&#xff0c;是项目建设单位向上级主管部门提交项目申请时所必须的文 件&#xff0c;是该项目建设筹建单位根据国民经济的发展、国家…

Spark高可用模式和Spark分布式Yarn环境安装

Spark分布式HA环境安装 图-12 高可用模式原理 因为在目前情况下&#xff0c;集群中只有一个Master&#xff0c;如果master挂掉&#xff0c;便无法对外提供新的服务&#xff0c;显然有单点故障问题&#xff0c;解决方法就是master的ha。 有两种方式解决单点故障&#xff0c;一…

无脑入单向无头链表的实现| ArrayList和LinkedList的区别

1. ArrayList的缺陷 上节课已经熟悉了ArrayList的使用&#xff0c;并且进行了简单模拟实现。通过源码知道&#xff0c;ArrayList底层使用数组来存储元素。 由于其底层是一段连续空间&#xff0c;当 在 ArrayList 任意位置插入或者删除元素时&#xff0c;就需要将后序元素整体往…