python基础知识(28)线程和进程

【Python】 进程与线程 在计算机操作系统中,进程是资源分配和调度的基本单位。每个进程都有自己独立的内存空间、代码执行上下文以及系统资源,如文件描述符、网络连接等。进程之间相互隔离,一个进程的崩溃通常不会影响到其他进程。 在 Python 中,多进程编程允许我们充分利用多核处理器的优势,并行地执行多个任务,从而提高程序的执行效率和响应速度。例如,在处理大规模数据计算、网络爬虫的并发请求、图像处理等任务时,多进程可以显著缩短执行时间。 阅读详情

线程与进程

线程与进程是操作系统里面的术语,简单来讲,每一个应用程序都有一个自己的进程。

操作系统会为这些进程分配一些执行资源,例如内存空间等。

在进程中,又可以创建一些线程,他们共享这些内存空间,并由操作系统调用,以便并行计算。

我们都知道现代操作系统比如 Mac OS X,UNIX,Linux,Windows 等可以同时运行多个任务。

打个比方,你一边在用浏览器上网,一边在听敲代码,一边用 Markdown 写博客,这就是多任务,至少同时有 3 个任务正在运行。

当然还有很多任务悄悄地在后台同时运行着,只是桌面上没有显示而已。

对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开 PyCharm 就是一个启动了一个 PtCharm 进程,打开 Markdown 就是启动了一个 Md 的进程。

虽然现在多核 CPU 已经非常普及了。

可是由于 CPU 执行代码都是顺序执行的,这时候我们就会有疑问,单核 CPU 是怎么执行多任务的呢?

其实就是操作系统轮流让各个任务交替执行,任务 1 执行 0.01 秒,切换到任务 2 ,任务 2 执行 0.01 秒,再切换到任务 3 ,执行 0.01秒……这样反复执行下去。

表面上看,每个任务都是交替执行的,但是,由于 CPU的执行速度实在是太快了,我们肉眼和感觉上没法识别出来,就像所有任务都在同时执行一样。

真正的并行执行多任务只能在多核 CPU 上实现,但是,由于任务数量远远多于 CPU 的核心数量,所以,操作系统也会自动把很多任务轮流调度到每个核心上执行。

有些进程不仅仅只是干一件事的啊,比如浏览器,我们可以播放时视频,播放音频,看文章,编辑文章等等,其实这些都是在浏览器进程中的子任务。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程(Thread)。

由于每个进程至少要干一件事,所以,一个进程至少有一个线程。

当然,一个进程也可以有多个线程,多个线程可以同时执行,多线程的执行方式和多进程是一样的,也是由操作系统在多个线程之间快速切换,让每个线程都短暂地交替运行,看起来就像同时执行一样。

那么在 Python 中我们要同时执行多个任务怎么办?

有两种解决方案:

一种是启动多个进程,每个进程虽然只有一个线程,但多个进程可以一块执行多个任务。

还有一种方法是启动一个进程,在一个进程内启动多个线程,这样,多个线程也可以一块执行多个任务。

当然还有第三种方法,就是启动多个进程,每个进程再启动多个线程,这样同时执行的任务就更多了,当然这种模型更复杂,实际很少采用。

总结一下就是,多任务的实现有3种方式:

  • 多进程模式;
  • 多线程模式;
  • 多进程+多线程模式。

同时执行多个任务通常各个任务之间并不是没有关联的,而是需要相互通信和协调,有时,任务 1 必须暂停等待任务 2 完成后才能继续执行,有时,任务 3 和任务 4 又不能同时执行,所以,多进程和多线程的程序的复杂度要远远高于我们前面写的单进程单线程的程序。

因为复杂度高,调试困难,所以,不是迫不得已,我们也不想编写多任务。

但是,有很多时候,没有多任务还真不行。

想想在电脑上看电影,就必须由一个线程播放视频,另一个线程播放音频,否则,单线程实现的话就只能先把视频播放完再播放音频,或者先把音频播放完再播放视频,这显然是不行的。

多线程编程

其实创建线程之后,线程并不是始终保持一个状态的,其状态大概如下:

  • New 创建
  • Runnable 就绪。等待调度
  • Running 运行
  • Blocked 阻塞。阻塞可能在 Wait Locked Sleeping
  • Dead 消亡

线程有着不同的状态,也有不同的类型。大致可分为:

  • 主线程
  • 子线程
  • 守护线程(后台线程)
  • 前台线程

简单了解完这些之后,我们开始看看具体的代码使用了。

1、线程的创建

Python 提供两个模块进行多线程的操作,分别是 thread 和 threading

前者是比较低级的模块,用于更底层的操作,一般应用级别的开发不常用。

因此,我们使用 threading 来举个例子:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

import time
import threading


class MyThread(threading.Thread):
    def run(self):
        for i in range(5):
            print('thread {}, @number: {}'.format(self.name, i))
            time.sleep(1)


def main():
    print("Start main threading")

    # 创建三个线程
    threads = [MyThread() for i in range(3)]
    # 启动三个线程
    for t in threads:
        t.start()

    print("End Main threading")


if __name__ == '__main__':
    main()

运行结果:

Start main threading
thread Thread-1, @number: 0
thread Thread-2, @number: 0
thread Thread-3, @number: 0
End Main threading
thread Thread-2, @number: 1
thread Thread-1, @number: 1
thread Thread-3, @number: 1
thread Thread-1, @number: 2
thread Thread-3, @number: 2
thread Thread-2, @number: 2
thread Thread-2, @number: 3
thread Thread-3, @number: 3
thread Thread-1, @number: 3
thread Thread-3, @number: 4
thread Thread-2, @number: 4
thread Thread-1, @number: 4

注意喔,这里不同的环境输出的结果肯定是不一样的。

2、线程合并(join方法)

上面的示例打印出来的结果来看,主线程结束后,子线程还在运行。那么我们需要主线程要等待子线程运行完后,再退出,要怎么办呢?

这时候,就需要用到 join 方法了。

在上面的例子,新增一段代码,具体如下:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

import time
import threading


class MyThread(threading.Thread):
    def run(self):
        for i in range(5):
            print('thread {}, @number: {}'.format(self.name, i))
            time.sleep(1)


def main():
    print("Start main threading")

    # 创建三个线程
    threads = [MyThread() for i in range(3)]
    # 启动三个线程
    for t in threads:
        t.start()

    # 一次让新创建的线程执行 join
    for t in threads:
        t.join()

    print("End Main threading")


if __name__ == '__main__':
    main()

从打印的结果,可以清楚看到,相比上面示例打印出来的结果,主线程是在等待子线程运行结束后才结束的。

Start main threading
thread Thread-1, @number: 0
thread Thread-2, @number: 0
thread Thread-3, @number: 0
thread Thread-1, @number: 1
thread Thread-3, @number: 1
thread Thread-2, @number: 1
thread Thread-2, @number: 2
thread Thread-1, @number: 2
thread Thread-3, @number: 2
thread Thread-2, @number: 3
thread Thread-1, @number: 3
thread Thread-3, @number: 3
thread Thread-3, @number: 4
thread Thread-2, @number: 4
thread Thread-1, @number: 4
End Main threading

3、线程同步与互斥锁

使用线程加载获取数据,通常都会造成数据不同步的情况。当然,这时候我们可以给资源进行加锁,也就是访问资源的线程需要获得锁才能访问。

其中 threading 模块给我们提供了一个 Lock 功能。

lock = threading.Lock()

在线程中获取锁

lock.acquire()

使用完成后,我们肯定需要释放锁

lock.release()

当然为了支持在同一线程中多次请求同一资源,Python 提供了可重入锁(RLock)。RLock 内部维护着一个 Lock 和一个 counter 变量,counter 记录了 acquire 的次数,从而使得资源可以被多次 require。直到一个线程所有的 acquire 都被 release,其他的线程才能获得资源。

那么怎么创建重入锁呢?也是一句代码的事情:

r_lock = threading.RLock()

4、Condition 条件变量

实用锁可以达到线程同步,但是在更复杂的环境,需要针对锁进行一些条件判断。

Python 提供了 Condition 对象。

使用 Condition 对象可以在某些事件触发或者达到特定的条件后才处理数据,Condition 除了具有 Lock 对象的 acquire 方法和 release 方法外,还提供了 wait 和 notify 方法。

线程首先 acquire 一个条件变量锁。如果条件不足,则该线程 wait,如果满足就执行线程,甚至可以 notify 其他线程。其他处于 wait 状态的线程接到通知后会重新判断条件。

其中条件变量可以看成不同的线程先后 acquire 获得锁,如果不满足条件,可以理解为被扔到一个( Lock 或 RLock )的 waiting 池。直到其他线程 notify 之后再重新判断条件。不断的重复这一过程,从而解决复杂的同步问题。

该模式常用于生产者消费者模式,具体看看下面在线购物买家和卖家的示例:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

import threading, time


class Consumer(threading.Thread):
    def __init__(self, cond, name):
        # 初始化
        super(Consumer, self).__init__()
        self.cond = cond
        self.name = name

    def run(self):
        # 确保先运行Seeker中的方法
        time.sleep(1)
        self.cond.acquire()
        print(self.name + ': 我这两件商品一起买,可以便宜点吗')
        self.cond.notify()
        self.cond.wait()
        print(self.name + ': 我已经提交订单了,你修改下价格')
        self.cond.notify()
        self.cond.wait()
        print(self.name + ': 收到,我支付成功了')
        self.cond.notify()
        self.cond.release()
        print(self.name + ': 等待收货')


class Producer(threading.Thread):
    def __init__(self, cond, name):
        super(Producer, self).__init__()
        self.cond = cond
        self.name = name

    def run(self):
        self.cond.acquire()
        # 释放对琐的占用,同时线程挂起在这里,直到被 notify 并重新占有琐。
        self.cond.wait()
        print(self.name + ': 可以的,你提交订单吧')
        self.cond.notify()
        self.cond.wait()
        print(self.name + ': 好了,已经修改了')
        self.cond.notify()
        self.cond.wait()
        print(self.name + ': 嗯,收款成功,马上给你发货')
        self.cond.release()
        print(self.name + ': 发货商品')


cond = threading.Condition()
consumer = Consumer(cond, '买家(两点水)')
producer = Producer(cond, '卖家(三点水)')
consumer.start()
producer.start()

输出的结果如下:

买家(两点水): 我这两件商品一起买,可以便宜点吗
卖家(三点水): 可以的,你提交订单吧
买家(两点水): 我已经提交订单了,你修改下价格
卖家(三点水): 好了,已经修改了
买家(两点水): 收到,我支付成功了
买家(两点水): 等待收货
卖家(三点水): 嗯,收款成功,马上给你发货
卖家(三点水): 发货商品

5、线程间通信

如果程序中有多个线程,这些线程避免不了需要相互通信的。那么我们怎样在这些线程之间安全地交换信息或数据呢?

从一个线程向另一个线程发送数据最安全的方式可能就是使用 queue 库中的队列了。创建一个被多个线程共享的 Queue 对象,这些线程通过使用 put() 和 get() 操作来向队列中添加或者删除元素。

# -*- coding: UTF-8 -*-
from queue import Queue
from threading import Thread

isRead = True


def write(q):
    # 写数据进程
    for value in ['两点水', '三点水', '四点水']:
        print('写进 Queue 的值为:{0}'.format(value))
        q.put(value)


def read(q):
    # 读取数据进程
    while isRead:
        value = q.get(True)
        print('从 Queue 读取的值为:{0}'.format(value))


if __name__ == '__main__':
    q = Queue()
    t1 = Thread(target=write, args=(q,))
    t2 = Thread(target=read, args=(q,))
    t1.start()
    t2.start()

输出的结果如下:

写进 Queue 的值为:两点水
写进 Queue 的值为:三点水
从 Queue 读取的值为:两点水
写进 Queue 的值为:四点水
从 Queue 读取的值为:三点水
从 Queue 读取的值为:四点水

Python 还提供了 Event 对象用于线程间通信,它是由线程设置的信号标志,如果信号标志位真,则其他线程等待直到信号接触。

Event 对象实现了简单的线程通信机制,它提供了设置信号,清楚信号,等待等用于实现线程间的通信。

  • 设置信号

使用 Event 的 set() 方法可以设置 Event 对象内部的信号标志为真。Event 对象提供了 isSe() 方法来判断其内部信号标志的状态。当使用 event 对象的 set() 方法后,isSet() 方法返回真

  • 清除信号

使用 Event 对象的 clear() 方法可以清除 Event 对象内部的信号标志,即将其设为假,当使用 Event 的 clear 方法后,isSet() 方法返回假

  • 等待

Event 对象 wait 的方法只有在内部信号为真的时候才会很快的执行并完成返回。当 Event 对象的内部信号标志位假时,则 wait 方法一直等待到其为真时才返回。

示例:

# -*- coding: UTF-8 -*-

import threading


class mThread(threading.Thread):
    def __init__(self, threadname):
        threading.Thread.__init__(self, name=threadname)

    def run(self):
        # 使用全局Event对象
        global event
        # 判断Event对象内部信号标志
        if event.isSet():
            event.clear()
            event.wait()
            print(self.getName())
        else:
            print(self.getName())
            # 设置Event对象内部信号标志
            event.set()

# 生成Event对象
event = threading.Event()
# 设置Event对象内部信号标志
event.set()
t1 = []
for i in range(10):
    t = mThread(str(i))
    # 生成线程列表
    t1.append(t)

for i in t1:
    # 运行线程
    i.start()

输出的结果如下:

1
0
3
2
5
4
7
6
9
8

6、后台线程

默认情况下,主线程退出之后,即使子线程没有 join。那么主线程结束后,子线程也依然会继续执行。如果希望主线程退出后,其子线程也退出而不再执行,则需要设置子线程为后台线程。Python 提供了 setDeamon 方法。

进程

Python 中的多线程其实并不是真正的多线程,如果想要充分地使用多核 CPU 的资源,在 Python 中大部分情况需要使用多进程。

Python 提供了非常好用的多进程包 multiprocessing,只需要定义一个函数,Python 会完成其他所有事情。

借助这个包,可以轻松完成从单进程到并发执行的转换。multiprocessing 支持子进程、通信和共享数据、执行不同形式的同步,提供了 Process、Queue、Pipe、Lock 等组件。

1、类 Process

创建进程的类:Process([group [, target [, name [, args [, kwargs]]]]])

  • target 表示调用对象
  • args 表示调用对象的位置参数元组
  • kwargs表示调用对象的字典
  • name为别名
  • group实质上不使用

下面看一个创建函数并将其作为多个进程的例子:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

import multiprocessing
import time


def worker(interval, name):
    print(name + '【start】')
    time.sleep(interval)
    print(name + '【end】')


if __name__ == "__main__":
    p1 = multiprocessing.Process(target=worker, args=(2, '两点水1'))
    p2 = multiprocessing.Process(target=worker, args=(3, '两点水2'))
    p3 = multiprocessing.Process(target=worker, args=(4, '两点水3'))

    p1.start()
    p2.start()
    p3.start()

    print("The number of CPU is:" + str(multiprocessing.cpu_count()))
    for p in multiprocessing.active_children():
        print("child   p.name:" + p.name + "\tp.id" + str(p.pid))
    print("END!!!!!!!!!!!!!!!!!")

输出的结果:

2、把进程创建成类

当然我们也可以把进程创建成一个类,如下面的例子,当进程 p 调用 start() 时,自动调用 run() 方法。

# -*- coding: UTF-8 -*-

import multiprocessing
import time


class ClockProcess(multiprocessing.Process):
    def __init__(self, interval):
        multiprocessing.Process.__init__(self)
        self.interval = interval

    def run(self):
        n = 5
        while n > 0:
            print("当前时间: {0}".format(time.ctime()))
            time.sleep(self.interval)
            n -= 1


if __name__ == '__main__':
    p = ClockProcess(3)
    p.start()

输出结果如下:

3、daemon 属性

想知道 daemon 属性有什么用,看下下面两个例子吧,一个加了 daemon 属性,一个没有加,对比输出的结果:

没有加 deamon 属性的例子:

# -*- coding: UTF-8 -*-
import multiprocessing
import time


def worker(interval):
    print('工作开始时间:{0}'.format(time.ctime()))
    time.sleep(interval)
    print('工作结果时间:{0}'.format(time.ctime()))


if __name__ == '__main__':
    p = multiprocessing.Process(target=worker, args=(3,))
    p.start()
    print('【EMD】')

输出结果:

【EMD】
工作开始时间:Mon Oct  9 17:47:06 2017
工作结果时间:Mon Oct  9 17:47:09 2017

在上面示例中,进程 p 添加 daemon 属性:

# -*- coding: UTF-8 -*-

import multiprocessing
import time


def worker(interval):
    print('工作开始时间:{0}'.format(time.ctime()))
    time.sleep(interval)
    print('工作结果时间:{0}'.format(time.ctime()))


if __name__ == '__main__':
    p = multiprocessing.Process(target=worker, args=(3,))
    p.daemon = True
    p.start()
    print('【EMD】')

输出结果:

【EMD】

根据输出结果可见,如果在子进程中添加了 daemon 属性,那么当主进程结束的时候,子进程也会跟着结束。所以没有打印子进程的信息。

4、join 方法

结合上面的例子继续,如果我们想要让子线程执行完该怎么做呢?

那么我们可以用到 join 方法,join 方法的主要作用是:阻塞当前进程,直到调用 join 方法的那个进程执行完,再继续执行当前进程。

因此看下加了 join 方法的例子:

import multiprocessing
import time


def worker(interval):
    print('工作开始时间:{0}'.format(time.ctime()))
    time.sleep(interval)
    print('工作结果时间:{0}'.format(time.ctime()))


if __name__ == '__main__':
    p = multiprocessing.Process(target=worker, args=(3,))
    p.daemon = True
    p.start()
    p.join()
    print('【EMD】')

输出的结果:

工作开始时间:Tue Oct 10 11:30:08 2017
工作结果时间:Tue Oct 10 11:30:11 2017
【EMD】

5、Pool

如果需要很多的子进程,难道我们需要一个一个的去创建吗?

当然不用,我们可以使用进程池的方法批量创建子进程。

例子如下:

# -*- coding: UTF-8 -*-

from multiprocessing import Pool
import os, time, random


def long_time_task(name):
    print('进程的名称:{0} ;进程的PID: {1} '.format(name, os.getpid()))
    start = time.time()
    time.sleep(random.random() * 3)
    end = time.time()
    print('进程 {0} 运行了 {1} 秒'.format(name, (end - start)))


if __name__ == '__main__':
    print('主进程的 PID:{0}'.format(os.getpid()))
    p = Pool(4)
    for i in range(6):
        p.apply_async(long_time_task, args=(i,))
    p.close()
    # 等待所有子进程结束后在关闭主进程
    p.join()
    print('【End】')

输出的结果如下:

主进程的 PID:7256
进程的名称:0 ;进程的PID: 1492
进程的名称:1 ;进程的PID: 12232
进程的名称:2 ;进程的PID: 4332
进程的名称:3 ;进程的PID: 11604
进程 2 运行了 0.6500370502471924 秒
进程的名称:4 ;进程的PID: 4332
进程 1 运行了 1.0830621719360352 秒
进程的名称:5 ;进程的PID: 12232
进程 5 运行了 0.029001712799072266 秒
进程 4 运行了 0.9720554351806641 秒
进程 0 运行了 2.3181326389312744 秒
进程 3 运行了 2.5331451892852783 秒
【End】

这里有一点需要注意: Pool 对象调用 join() 方法会等待所有子进程执行完毕,调用 join() 之前必须先调用 close() ,调用close() 之后就不能继续添加新的 Process 了。

请注意输出的结果,子进程 0,1,2,3是立刻执行的,而子进程 4 要等待前面某个子进程完成后才执行,这是因为 Pool 的默认大小在我的电脑上是 4,因此,最多同时执行 4 个进程。这是 Pool 有意设计的限制,并不是操作系统的限制。如果改成:

p = Pool(5)

就可以同时跑 5 个进程。

6、进程间通信

Process 之间肯定是需要通信的,操作系统提供了很多机制来实现进程间的通信。Python 的 multiprocessing 模块包装了底层的机制,提供了Queue、Pipes 等多种方式来交换数据。

以 Queue 为例,在父进程中创建两个子进程,一个往 Queue 里写数据,一个从 Queue 里读数据:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

from multiprocessing import Process, Queue
import os, time, random


def write(q):
    # 写数据进程
    print('写进程的PID:{0}'.format(os.getpid()))
    for value in ['两点水', '三点水', '四点水']:
        print('写进 Queue 的值为:{0}'.format(value))
        q.put(value)
        time.sleep(random.random())


def read(q):
    # 读取数据进程
    print('读进程的PID:{0}'.format(os.getpid()))
    while True:
        value = q.get(True)
        print('从 Queue 读取的值为:{0}'.format(value))


if __name__ == '__main__':
    # 父进程创建 Queue,并传给各个子进程
    q = Queue()
    pw = Process(target=write, args=(q,))
    pr = Process(target=read, args=(q,))
    # 启动子进程 pw
    pw.start()
    # 启动子进程pr
    pr.start()
    # 等待pw结束:
    pw.join()
    # pr 进程里是死循环,无法等待其结束,只能强行终止
    pr.terminate()

输出的结果为:

读进程的PID:13208
写进程的PID:10864
写进 Queue 的值为:两点水
从 Queue 读取的值为:两点水
写进 Queue 的值为:三点水
从 Queue 读取的值为:三点水
写进 Queue 的值为:四点水
从 Queue 读取的值为:四点水
了解你的GPU:深入探讨AMD SMI 2024年9月17日 作者:Matt Elliott对于使用AMD硬件的系统管理员和高级用户来说,性能优化和高效的资源监控至关重要。AMD系统管理界面命令行工具`amd-smi`正是为了解决这些需求而设计的。amd-smi是一个多功能的命令行工具,专门用于管理和监控AMD硬件,主要侧重于GPU。作为未来取代`rocm-smi`的工具,`amd-smi`有望成为跨广泛设备的AMD硬件管理的主要工具。 阅读详情

相关推荐

PT-Thread的使用教程

PT-Thread保姆级使用教程

负吾键来的博客 3866

pt-thread的使用

1. pt-thread使用 官网:http://dunkels.com/adam/pt/index.html 1.1 使用示例 ptthread 有两种运行任务的方式,一种是switch,另一种是goto。这里使用的是switch,在lc.h文件中包含相应头文件即可。#include “lc-switch.h” //PT_BEGIN(p); { char PT_YIELD_FLAG = 1; //LC_RESUME((pt)->lc) switch(p->lc)

qq_25355591的博客 837

python-进程和线程

进程: 一个程序的执行实例就是一个进程,表现为程序是源代码编译后的文件,而这些文件存放在磁盘上。当程序被操作系统加载到内存中,就是进程。 进程中存放着指令和数据(资源),它也是线程的容器。 进程( Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。 Linux进程有父进程、子进程,Windows的进程是平等关系 线程: 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运行单位。 线程,有时被称为轻量级进程

jjliu的博客 1370

Python 中进程和线程

文章目录线程和进程一、 什么是进程 / 线程1、 引论2、 线程3、 进程4、 区别5、 使用二、 多线程使用1、 常用方法2、 常用参数3、 多线程的应用3.1 重写线程法3.2 直接调用法4、 线程间数据的共享三、 多进程使用1、 简介2、 应用2.1 重写进程法2.2 直接调用法3、 进程之间的数据共享3.1 Lock 方法3.2 Manager 方法四、 池并发1、 语法2、 获取 CPU 数量3、 线程池3、 进程池 线程和进程 一、 什么是进程 / 线程 1、 引论 众所周知,CPU是计算机的

一个专注于机器学习基础与实战的技术博客,内容涵盖算法推导、模型实现、数学原理与代码实践。用通俗的语言解析复杂概念,记录学习过程中的思考与总结,适合机器学习爱好者和从业者参考。 3228

Python多进程及多线程基础

关于进程和线程的基础知识,之前已经分享过一些文章,下面把一些基础知识,再总结下(重点:面试常问):启动一个程序,就默认创建一个主进程,在一个主进程中默认创建一个主线程进程是系统资源分配和...

吾非同 497

复合材料RVE建模与力学性能分析实战指南

代表体积元(RVE)建模是复合材料多尺度分析的核心技术,通过建立微观结构与宏观性能的定量关联,可准确预测材料力学行为。本文基于ABAQUS平台,详细解析三材料(纤维/基体/界面相)RVE建模全流程,包括参数化几何建模、周期性网格划分策略、材料属性定义技巧等关键技术环节。针对碳纤维增强环氧树脂等典型复合材料,提供网格控制参数建议和材料参数参考表,并重点说明周期性边界条件的实现方法与验证标准。通过Python脚本自动化处理和优化分析流程,可显著提升计算效率,为复合材料设计提供可靠仿真依据。

weixin_34062469的博客 549

【Python】进程和线程

一般而言,在一个应用程序中(即进程),一个线程往往不是孤立存在的,常常需要和其他线程通信,以执行特定的任务。进程池就是实现已经创建好的进程,进程池里面放的都是进程,进程池可以根据任务自动创建进程,合理利用进程池中的进程完成多项任务。进程表示的是一个正在执行的程序,每个进程都拥有自己的地址空间、内存、数据栈,以及其他用于跟踪执行的辅助数据。线程也叫轻量级进程,它是一个基本的CPU执行单元,也是程序执行过程中的最小单元,曲线程ID、程序计数器、寄存器集合和堆栈共同组成。进程的亲缘关系是指父子进程关系。

2401_86008949的博客 1269

泛微Ecology9接口调用全流程:从配置到实战Java代码解析

本文详细解析了泛微Ecology9系统接口的完整调用流程,涵盖安全架构、服务端配置与客户端Java实战代码。重点阐述了基于RSA加密的认证机制、Token管理策略,并提供了企业级集成的核心代码示例与生产环境调优建议,帮助开发者安全、高效地实现系统对接。

m9n0o的博客 838

Python进程和线程

Python实现多任务主要依赖多进程和多线程。进程通过multiprocessing模块创建,能并行执行任务但资源开销大且不共享全局变量。线程使用threading模块,共享全局变量且资源开销小,但不能充分利用多核。创建进程或线程需指定目标函数和参数,通过start()启动。线程执行顺序由CPU调度决定。使用时需注意主进程/线程与子进程/线程的结束顺序,可设置守护进程/线程或显式销毁来管理。线程间共享变量可能引发数据竞争,需同步以确保数据一致性。选择多进程或多线程应基于具体需求。

taisu001的博客 1369

西门子博途系列学习笔记SCL(三)______自由口通讯(RS485轮询程序)

西门子博途V16系列学习笔记SCL(三)___自由口通讯轮询程序(RS485) 西门子博途系列学习笔记SCL(三)______自由口通讯(RS485轮询程序) 文章目录西门子博途V16系列学习笔记SCL(三)___自由口通讯轮询程序(RS485)前言一、FreePort自由口通讯是什么?二、使用步骤1.模块参数定义2.定义FB功能块参数:3.程序代码如下(每天写代码100行,学不会你来找我):总结 前言 很长时间都没有更新了,主要是最近在学习罗克韦尔的STUDIO5000PLC编程软件,怎么说,和博

weixin_42940283的博客 1万+

freertos移植心得

1.freertos移植msp430 今天终于移植成功了freertos。现在写下这篇博文来整理这一路移植过程中遇到的问题和心得。 由于使用的是IAR FOR MSP430的IDE,博文只讨论在IAR下的移植。本文针对的是官方支持的平台架构下的移植,不使用官方提供的demo,得到的是一个纯洁版的系统。 1.下载源代码 在freertos的官网下载一份最新的源代码点击打开链接。 2.选择平

一条狗的博客 4173

python进程和线程

2、multiprocessing.Process类的join()方法可以阻塞主进程,当子进程没有进行完成的时候,主进程hold。2、threading.Thread类的join()方法可以阻塞主进程,当子线程没有进行完成的时候,主线程hold。3、可以通过继承multiprocessing.Process并重写run()函数的方法来实现多线程。1、线程通过multiprocessing.Process类的start()方法启动。1、线程通过threading.Thread类的start()方法启动。

haixiao0720的博客 1645

A Side Scan Sonar Image Denoising Algorithm Based on Compound of Fuzzy Weighted Average and Kalman F

Abstract 水下侧扫声纳图像的噪声来源:高斯噪声、脉冲、斑点噪声。 传统方法只能移除部分噪声,并且去噪后容易造成细节模糊。 本文在考虑到噪声的随机性以后,提出一种融合了模糊加权平均和卡尔曼滤波的去噪方法。 在最大化保留图像细节的基础上,同时去除高斯噪声和脉冲噪声 一.Introduction 由于海底环境和声波自身干涉的影响,声纳图像生成的图像难免会有噪点。声纳采集的图像通常会有高斯噪声、脉...

qq_44516871的博客 928

Python中的进程和线程

Python中的进程和线程 一.进程的概念 一个正在运行的程序或者软件就是一个进程,它是操作系统进行资源分配的基本单位,也就是说每启动一个进程,操作系统都会给其分配一定的运行资源(内存资源)保证进程的运行。 注意: 一个程序运行后至少有一个进程,一个进程默认有一个线程,进程里面可以创建多个线程,线程是依附在进程里面的,没有进程就没有线程. 并行:多个cpu同时处理多个程序 并发:一个cpu在一个很小的时间段之内在多个程序之间来回切换执行,切换的时间由操作系统决定,但时间比较小 进程的作用: 单进程效果图:

Lonely_Fishes的博客 1466

【FPGA教程案例96】控制案例1——基于FPGA的自适应PID控制器verilog实现

首先,我们复习下课程传统的PID控制器,往往存在调整速度较慢,超调过大等缺点。为了解决这个问题,在实际的PID应用中,需要实时的调整PID的控制参数,以达到加快PID控制速度,降低超调等目标。目前,自适应PID控制器,一般有误差反馈调整,模糊控制器调整,神经网络调整。其中模糊控制器调整,神经网络调整较为复杂,在入门案例中不做介绍,在本课程中,我们将实现相对略微简单点的基于误差反馈调整的自适应PID控制器。

FPGA/MATLAB学习教程/源码/项目合作开发 6203

基于STM32设计的个人健康检测仪(华为云IOT)(191)

本系统采用华为云物联网平台实现数据云端存储与分析,并通过自研手机APP提供远程监控界面,让用户无论身处何地都能及时掌握自身的健康数据,为用户提供个性化的健康管理方案,同时也为医疗机构提供了便捷的数据获取途径,助力实现智能化、精细化的医疗服务。

1678

Python进阶————进程和线程

Python中多进程与多线程详解

记录学习笔记 1221

实战:批量抓取免费代理IP全流程(附自动验证+失效剔除,爬虫抗封必备)

本文分享了一套从免费代理IP中筛选可用高匿代理的实用方案。作者通过半年实践,总结出"批量抓取+精准验证+动态维护"的方法,能从2000条免费IP中筛选出30-50条可用代理,满足中小规模爬虫需求。 方案包含四个核心环节: 多源代理抓取:针对快代理、西刺代理等不同网站定制解析规则 三层验证机制:检查有效性、匿名度和响应速度 代理池自动维护:实时淘汰失效IP Scrapy整合实战:提供可直接复用的代码 文章特别指出免费代理的三大痛点:存活率低(80%10分钟内失效)、匿名性差(仅5%是高匿代

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1602

Python进程、线程、协程

Python进程、线程、协程 线程 ​ 基于_thread的threading模块,提供了更加方便的api来处理进程 import threading import time def worker(num): time.sleep(1) print("The num is %d" %num) return for i in range(20): t = thre...

王清欢的博客 8493

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Python中的协程、线程和进程

协程、多线程和多进程都是实现程序并发执行的方法,不过它们在工作方式和适合的应用场景上存在一些区别。

NLP工程化 2141

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

python进程线程基础知识

当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。观看全面零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。#kwargs是一个字典,在字典的key对应的是函数的参数名,字典的值对应函数的值,两个参数的顺序可以更换。#同样的方法创建进程,所不同的是第二个参数,第二个参数同样的是给定义的函数传入参数,不同于args的是。

m0_61549953的博客 1002

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Python 进程和线程-进程 vs. 线程

这种计算密集型任务虽然也可以用多任务完成,但是任务越多,花在任务切换的时间就越多,CPU执行任务的效率就越低,所以,要最高效地利用CPU,计算密集型任务同时进行的数量应当等于CPU的核心数。对于IO密集型任务,最合适的语言就是开发效率最高(代码量最少)的语言,脚本语言是首选,C语言开发效率最差。假设你打算切换到多任务模型,可以先做1分钟语文,再切换到数学作业,做1分钟,再切换到英语,以此类推,只要切换速度足够快,这种方式就和单核CPU执行多任务是一样的了,以幼儿园小朋友的眼光来看,你就正在同时写5科作业。

分享编程知识与技巧 致力于技术交流与学习 找我合作私聊 有偿解决计算机问题 1197

python 判断线程状态_Python多进程及多线程基础

关于进程和线程的基础知识,之前已经分享过一些文章,下面把一些基础知识,再总结下(重点:面试常问):启动一个程序,就默认创建一个主进程,在一个主进程中默认创建一个主线程进程是系统资源分配和调度的基本单位,线程存在于进程中,线程是CPU调度和分配的基本单位。进程之间相互独立,同一个变量,多进程中各自会拷贝一份,而同一个进程的多个线程是共享内存的,所有变量都由所有线程共享,从而提升程序的运行效率。进程之...

weixin_39966020的博客 8110
上一篇: python基础知识(27)元类 2
下一篇: python基础知识(29)正则表达式
ty_wink
博客等级 码龄4年 495粉丝 29原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值