Qt扫盲-Qt Concurrent概述
Qt Concurrent概述
- 一、概述
- 二、Concurrent Map 和 Map- reduce
- 1. 并发 Map
- 2. 并发 Map-Reduce
- 3. 其他API特性
- 1. 使用迭代器而不是Sequence
- 3. 阻塞变量
- 4. 使用成员函数
- 5. 使用函数对象
- 6. 包装接受多个参数的函数
- 三、Concurrent Filter and Filter-Reduce
- 1. 并发过滤器
- 2. 并发Filter-Reduce
- 3. 其他API特性
- 1. 使用迭代器而不是Sequence
- 2. 使用成员函数
- 3. 使用函数对象
- 4. 包装接受多个参数的函数
- 四、Concurrent Run
- 1. 在单独的线程中运行函数
- 2. 向函数传递参数
- 3. 从函数返回值
- 4. 其他API特性
- 1. 使用成员函数
- 2. 使用Lambda函数
一、概述
QtConcurrent 命名空间提供了一些高级api,可以在不使用互斥锁、读写锁、等待条件或信号量等低级线程原语的情况下编写多线程程序。使用QtConcurrent编写的程序会根据可用的处理器核数自动调整所使用的线程数。这意味着今天编写的应用程序在将来部署到多核系统上时将继续扩展。
QtConcurrent包括用于并行列表处理的函数式编程风格api,包括用于共享内存(非分布式)系统的 MapReduce 和 FilterReduce 实现,以及用于管理GUI应用程序中的异步计算的类:
- Concurrent Map 和 Map- reduce
QtConcurrent::map() 对容器中的每个项应用一个函数,就地修改这些项 (不返回,原地修改)。
QtConcurrent::mapped() 类似于map(),不同之处在于它返回一个带有修改的新容器 (返回修改)。
QtConcurrent::mappedReduced() 类似于map(),不同之处在于修改后的结果被简化或折叠为单个结果。 - Concurrent Filter和Filter- reduce
QtConcurrent::filter() 根据过滤器函数的结果从容器中删除所有项。
QtConcurrent::filtered() 类似于filter(),不同之处在于它返回一个包含过滤结果的新容器。
QtConcurrent::filteredReduced() 类似于filtered(),不同之处在于过滤后的结果被简化或折叠为单个结果。 - 并发运行 (Concurrent Run)
QtConcurrent::run() 在另一个线程中运行函数。 - QFuture 表示异步计算的结果。
- QFutureIterator 允许通过QFuture得到的结果进行迭代。
- QFutureWatcher 允许使用信号和插槽监控QFuture。
- QFutureSynchronizer 是一个方便的类,可以自动同步多个QFutures。
Qt Concurrent 支持几种与 stl 兼容的容器和迭代器类型,但最适合具有随机访问迭代器的Qt容器,如 QList 或 QVector。map 和 filter 函数接受容器和 begin/end 迭代器。
STL迭代器支持概述:
迭代器类型 | 示例类 | 支持状态 |
---|---|---|
输入迭代器 | 不支持 | |
输出迭代器 | 不支持 | |
前向迭代器 | std:: slist | 支持 |
双向迭代器 | QLinkedList, std::list | 支持 |
随机存取迭代器 | QList, QVector, std::vector | 支持和推荐 |
在Qt Concurrent迭代大量轻量级项的情况下,随机访问迭代器可以更快,因为它们允许跳转到容器中的任何点。此外,使用随机访问迭代器允许 Qt Concurrent 通过 QFuture::progressValue() 和 QFutureWatcher::progressValueChanged() 提供进度信息。
非就地修改函数,如 mapped() 和 filtered(),在调用时生成一个容器的副本。如果使用STL容器,此复制操作可能需要一些时间,在这种情况下,Qt 建议为容器指定 开始和结束 迭代器。
二、Concurrent Map 和 Map- reduce
QtConcurrent::map()、QtConcurrent::mapped()和QtConcurrent::mappedReduced()函数对序列(如QList或QVector)中的项并行运行计算。QtConcurrent::map()就地修改序列,QtConcurrent::mapped()返回一个包含修改内容的新序列,而QtConcurrent::mappedReduced()返回一个结果。
这些函数是Qt Concurrent框架的一部分。
上面的每个函数都有一个阻塞变量,它返回最终结果而不是 QFuture。我们可以像使用异步变量一样使用它们。
QList<QImage> images = ...;// Each call blocks until the entire operation is finished.QList<QImage> future = QtConcurrent::blockingMapped(images, scaled);QtConcurrent::blockingMap(images, scale);QImage collage = QtConcurrent::blockingMappedReduced(images, scaled, addToCollage);
注意,上面的结果类型不是QFuture对象,而是真正的结果类型(在本例中是QList和QImage)。
1. 并发 Map
QtConcurrent::mapped() 接受输入序列和映射函数。然后对序列中的每一项调用该映射函数,并返回一个包含映射函数返回值的新序列。
map函数的格式必须是:
U function(const T &t);
T 和 U可以是任何类型(它们甚至可以是相同的类型),但是T必须匹配存储在序列中的类型。函数返回修改或映射的内容。
这个例子展示了如何将一个比例函数应用于一个序列中的所有项:
QImage scaled(const QImage &image){return image.scaled(100, 100);}QList<QImage> images = ...;QFuture<QImage> thumbnails = QtConcurrent::mapped(images, scaled);
该 Map 的结果可通过QFuture获得。有关如何在应用程序中使用QFuture的更多信息,请参阅QFuture和QFutureWatcher文档。
如果我们想就地修改序列,请使用QtConcurrent::map()。map函数必须是这样的形式:
U function(T &t);
注意,没有使用map函数的返回值和返回类型。
使用QtConcurrent::map()类似于使用QtConcurrent::mapped():
void scale(QImage &image){image = image.scaled(100, 100);}QList<QImage> images = ...;QFuture<void> future = QtConcurrent::map(images, scale);
由于序列被就地修改,QtConcurrent::map()不会通过QFuture返回任何结果。但是,我们仍然可以使用QFuture和QFutureWatcher来监视 Map 的状态。
2. 并发 Map-Reduce
QtConcurrent::mappedReduced()类似于QtConcurrent::mapped(),但不是返回带有新结果的序列,而是使用reduce函数将结果组合成单个值。
QFuture<ResultType> QtConcurrent:: mapappedreduced (const Sequence &sequence, MapFunctor mapFunction, ReduceFunctor reduceFunction, QtConcurrent::ReduceOptions ReduceOptions = ReduceOptions(UnorderedReduce | SequentialReduce))
含义:按顺序为每个Item 调用mapFunction一次。每个mapFunction的返回值传递给reduceFunction,最后获得一个结果。
reduce函数的形式必须是:
V function(T &result, const U &intermediate)
T是最终结果的类型,U是映射函数的返回类型。注意,这里没有使用reduce函数的返回值和返回类型。
像这样调用QtConcurrent::mappedReduced():
void addToCollage(QImage &collage, const QImage &thumbnail){QPainter p(&collage);static QPoint offset = QPoint(0, 0);p.drawImage(offset, thumbnail);offset += ...;}QList<QImage> images = ...;QFuture<QImage> collage = QtConcurrent::mappedReduced(images, scaled, addToCollage);
对于map函数返回的每个结果,reduce函数将被调用一次,并且应该将中间值合并到result变量中。
QtConcurrent::mappedReduced() 保证一次只有一个线程调用reduce,所以没有必要使用互斥锁来锁定结果变量。
ReduceOptions enum提供了一种方法来控制执行缩减的顺序。如果使用QtConcurrent::UnorderedReduce(默认值),则顺序是未定义的,而QtConcurrent::OrderedReduce确保按原始序列的顺序进行缩减。
3. 其他API特性
1. 使用迭代器而不是Sequence
以上每个函数都有一个变体,它接受迭代器范围而不是序列。使用它们的方式与序列变体相同:
QList<QImage> images = ...;QFuture<QImage> thumbnails = QtConcurrent::mapped(images.constBegin(), images.constEnd(), scaled);// Map in-place only works on non-const iterators.
QFuture<void> future = QtConcurrent::map(images.begin(), images.end(), scale);QFuture<QImage> collage = QtConcurrent::mappedReduced(images.constBegin(), images.constEnd(), scaled, addToCollage);
3. 阻塞变量
上面的每个函数都有一个阻塞变量,它返回最终结果而不是QFuture。我们可以像使用异步变量一样使用它们。
QList<QImage> images = ...;// Each call blocks until the entire operation is finished.QList<QImage> future = QtConcurrent::blockingMapped(images, scaled);QtConcurrent::blockingMap(images, scale);QImage collage = QtConcurrent::blockingMappedReduced(images, scaled, addToCollage);
注意,上面的结果类型不是QFuture对象,而是真正的结果类型(在本例中是QList和QImage)。
4. 使用成员函数
QtConcurrent::map()、QtConcurrent::mapped()和QtConcurrent::mappedReduced()接受指向成员函数的指针。成员函数类类型必须与序列中存储的类型匹配:
// Squeeze all strings in a QStringList.QStringList strings = ...;QFuture<void> squeezedStrings = QtConcurrent::map(strings, &QString::squeeze);// Swap the rgb values of all pixels on a list of images.QList<QImage> images = ...;QFuture<QImage> bgrImages = QtConcurrent::mapped(images, &QImage::rgbSwapped);// Create a set of the lengths of all strings in a list.QStringList strings = ...;QFuture<QSet<int> > wordLengths = QtConcurrent::mappedReduced(strings, &QString::length, &QSet<int>::insert);
注意,当使用QtConcurrent::mappedReduced()时,你可以自由地混合使用普通函数和成员函数:
// Can mix normal functions and member functions with QtConcurrent::mappedReduced().// Compute the average length of a list of strings.extern void computeAverage(int &average, int length);QStringList strings = ...;QFuture<int> averageWordLength = QtConcurrent::mappedReduced(strings, &QString::length, computeAverage);// Create a set of the color distribution of all images in a list.extern int colorDistribution(const QImage &string);QList<QImage> images = ...;QFuture<QSet<int> > totalColorDistribution = QtConcurrent::mappedReduced(images, colorDistribution, QSet<int>::insert);
5. 使用函数对象
QtConcurrent::map()、QtConcurrent::mapped()和QtConcurrent::mappedReduced()接受map函数的函数对象。这些函数对象可用于向函数调用添加状态。result_type typepedef必须定义函数调用操作符的结果类型:
struct Scaled{Scaled(int size): m_size(size) { }typedef QImage result_type;QImage operator()(const QImage &image){return image.scaled(m_size, m_size);}int m_size;};QList<QImage> images = ...;QFuture<QImage> thumbnails = QtConcurrent::mapped(images, Scaled(100));
对于reduce函数,不直接支持函数对象。但是,当显式指定了缩减结果的类型时,可以使用函数对象:
struct ImageTransform{void operator()(QImage &result, const QImage &value);};QFuture<QImage> thumbNails =QtConcurrent::mappedReduced<QImage>(images,Scaled(100),ImageTransform(),QtConcurrent::SequentialReduce);
6. 包装接受多个参数的函数
如果我们想使用接受多个参数的map函数,可以使用lambda函数或std::bind()将其转换为接受一个参数的函数。
作为示例,我们将使用QImage::scaledToWidth():
QImage QImage::scaledToWidth(int width, Qt::TransformationMode) const;
scaledToWidth接受三个参数(包括“this”指针),不能直接与QtConcurrent::mapped()一起使用,因为QtConcurrent::mapped()期望一个函数接受一个参数。为了使用QImage::scaledToWidth()和QtConcurrent::mapped(),我们必须提供一个宽度和转换模式的值:
QList<QImage> images = ...;std::function<QImage(const QImage &)> scale = [](const QImage &img) {return img.scaledToWidth(100, Qt::SmoothTransformation);};QFuture<QImage> thumbnails = QtConcurrent::mapped(images, scale);
三、Concurrent Filter and Filter-Reduce
QtConcurrent::filter()、QtConcurrent::filtered()和QtConcurrent::filteredReduced()函数对序列中的项进行并行过滤,比如QList或QVector。QtConcurrent::filter()就地修改序列,QtConcurrent::filtered()返回包含过滤内容的新序列,QtConcurrent::filteredReduced()返回单个结果。
这些函数是Qt Concurrent框架的一部分。
上面的每个函数都有一个阻塞变量,它返回最终结果而不是QFuture。您可以像使用异步变体一样使用它们。
QStringList strings = ...;// each call blocks until the entire operation is finishedQStringList lowerCaseStrings = QtConcurrent::blockingFiltered(strings, allLowerCase);QtConcurrent::blockingFilter(strings, allLowerCase);QSet<QString> dictionary = QtConcurrent::blockingFilteredReduced(strings, allLowerCase, addToDictionary);
注意,上面的结果类型不是QFuture对象,而是真正的结果类型(在本例中是QStringList和QSet)。
1. 并发过滤器
QtConcurrent::filtered()接受一个输入序列和一个过滤函数。然后对序列中的每个项调用此筛选函数,并返回一个包含筛选值的新序列。
过滤器函数必须是这样的:
bool function(const T &t);
T必须匹配存储在序列中的类型。如果应该保留该项,则返回true;如果应该丢弃该项,则返回false。
这个例子展示了如何从QStringList中保留所有小写的字符串:
bool allLowerCase(const QString &string){return string.lowered() == string;}QStringList strings = ...;QFuture<QString> lowerCaseStrings = QtConcurrent::filtered(strings, allLowerCase);
过滤器的结果可以通过QFuture获得。有关如何在应用程序中使用QFuture的更多信息,请参阅QFuture和QFutureWatcher文档。
如果你想就地修改一个序列,使用QtConcurrent::filter():
QStringList strings = ...;QFuture<void> future = QtConcurrent::filter(strings, allLowerCase);
由于序列被就地修改,QtConcurrent::filter()不会通过QFuture返回任何结果。但是,您仍然可以使用QFuture和QFutureWatcher来监视过滤器的状态。
2. 并发Filter-Reduce
QtConcurrent::filteredReduced()类似于QtConcurrent::filtered(),但不是返回一个包含过滤结果的序列,而是使用reduce函数将结果组合成一个值。
reduce函数的形式必须是:
V function(T &result, const U &intermediate)
T是最终结果的类型,U是被过滤项目的类型。注意,这里没有使用reduce函数的返回值和返回类型。
像这样调用QtConcurrent::filteredReduced():
void addToDictionary(QSet<QString> &dictionary, const QString &string){dictionary.insert(string);}QStringList strings = ...;QFuture<QSet<QString> > dictionary = QtConcurrent::filteredReduced(strings, allLowerCase, addToDictionary);
对于过滤器函数保存的每个结果,reduce函数将被调用一次,并且应该将中间结果合并到结果变量中。
QtConcurrent::filteredReduced()保证一次只有一个线程调用reduce,所以没有必要使用互斥锁来锁定结果变量。ReduceOptions enum提供了一种方法来控制执行缩减的顺序。
3. 其他API特性
1. 使用迭代器而不是Sequence
以上每个函数都有一个变体,它接受迭代器范围而不是序列。使用它们的方式与序列变体相同:
QStringList strings = ...;QFuture<QString> lowerCaseStrings = QtConcurrent::filtered(strings.constBegin(), strings.constEnd(), allLowerCase);// filter in-place only works on non-const iteratorsQFuture<void> future = QtConcurrent::filter(strings.begin(), strings.end(), allLowerCase);QFuture<QSet<QString> > dictionary = QtConcurrent::filteredReduced(strings.constBegin(), strings.constEnd(), allLowerCase, addToDictionary);
2. 使用成员函数
QtConcurrent::filter()、QtConcurrent::filtered()和QtConcurrent::filteredReduced()接受指向成员函数的指针。成员函数类类型必须与序列中存储的类型匹配:
// keep only images with an alpha channelQList<QImage> images = ...;QFuture<void> alphaImages = QtConcurrent::filter(images, &QImage::hasAlphaChannel);// retrieve gray scale imagesQList<QImage> images = ...;QFuture<QImage> grayscaleImages = QtConcurrent::filtered(images, &QImage::isGrayscale);// create a set of all printable charactersQList<QChar> characters = ...;QFuture<QSet<QChar> > set = QtConcurrent::filteredReduced(characters, &QChar::isPrint, &QSet<QChar>::insert);
注意,当使用QtConcurrent::filteredReduced()时,你可以自由地混合使用普通函数和成员函数:
// can mix normal functions and member functions with QtConcurrent::filteredReduced()// create a dictionary of all lower cased stringsextern bool allLowerCase(const QString &string);QStringList strings = ...;QFuture<QSet<int> > averageWordLength = QtConcurrent::filteredReduced(strings, allLowerCase, QSet<QString>::insert);// create a collage of all gray scale imagesextern void addToCollage(QImage &collage, const QImage &grayscaleImage);QList<QImage> images = ...;QFuture<QImage> collage = QtConcurrent::filteredReduced(images, &QImage::isGrayscale, addToCollage);
3. 使用函数对象
QtConcurrent::filter()、QtConcurrent::filtered()和QtConcurrent::filteredReduced()接受过滤函数的函数对象。这些函数对象可用于向函数调用添加状态。result_type typepedef必须定义函数调用操作符的结果类型:
struct StartsWith{StartsWith(const QString &string): m_string(string) { }typedef bool result_type;bool operator()(const QString &testString){return testString.startsWith(m_string);}QString m_string;};QList<QString> strings = ...;QFuture<QString> fooString = QtConcurrent::filtered(strings, StartsWith(QLatin1String("Foo")));
对于reduce函数,不直接支持函数对象。但是,当显式指定了缩减结果的类型时,可以使用函数对象:
struct StringTransform{void operator()(QString &result, const QString &value);};QFuture<QString> fooString =QtConcurrent::filteredReduced<QString>(strings,StartsWith(QLatin1String("Foo")),StringTransform());
4. 包装接受多个参数的函数
如果您想使用接受多个参数的过滤器函数,可以使用lambda函数或std::bind()将其转换为接受一个参数的函数。
作为一个例子,我们使用QString::contains():
bool QString::contains(const QRegularExpression ®exp) const;
QString::contains()接受2个参数(包括“this”指针),不能直接与QtConcurrent::filtered()一起使用,因为QtConcurrent::filtered()期望一个函数接受一个参数。要将QString::contains()与QtConcurrent::filtered()一起使用,我们必须为regexp参数提供一个值:
QStringList strings = ...;QFuture<QString> future = QtConcurrent::filtered(list, [](const QString &str) {return str.contains(QRegularExpression("^\\S+$")); // matches strings without whitespace});
四、Concurrent Run
QtConcurrent::run()函数在一个单独的线程中运行一个函数。函数的返回值可以通过QFuture API获得。
这个函数是Qt Concurrent框架的一部分。
1. 在单独的线程中运行函数
要在另一个线程中运行一个函数,使用QtConcurrent::run():
extern void aFunction();QFuture<void> future = QtConcurrent::run(aFunction);
这将在从默认QThreadPool获得的单独线程中运行function。您可以使用QFuture和QFutureWatcher类来监视函数的状态。
要使用专用线程池,你可以将QThreadPool作为第一个参数:
extern void aFunction();QThreadPool pool;QFuture<void> future = QtConcurrent::run(&pool, aFunction);
2. 向函数传递参数
向函数传递参数是通过将参数添加到函数名后面的QtConcurrent::run()调用中来完成的。例如:
extern void aFunctionWithArguments(int arg1, double arg2, const QString &string);int integer = ...;double floatingPoint = ...;QString string = ...;QFuture<void> future = QtConcurrent::run(aFunctionWithArguments, integer, floatingPoint, string);
在调用QtConcurrent::run()时生成每个参数的副本,并在线程开始执行函数时将这些值传递给线程。
调用QtConcurrent::run()后对参数所做的更改对线程是不可见的。
3. 从函数返回值
函数的任何返回值都可以通过QFuture获得:
extern QString functionReturningAString();QFuture<QString> future = QtConcurrent::run(functionReturningAString);...QString result = future.result();
如上所述,传递参数是这样做的:
extern QString someFunction(const QByteArray &input);QByteArray bytearray = ...;QFuture<QString> future = QtConcurrent::run(someFunction, bytearray);...QString result = future.result();
注意,QFuture::result()函数阻塞并等待结果可用。当函数完成执行并且结果可用时,使用QFutureWatcher获取通知。
4. 其他API特性
1. 使用成员函数
QtConcurrent::run()也接受成员函数的指针。第一个实参必须是const引用或指向类实例的指针。在调用const成员函数时,通过const引用传递是有用的;指针传递对于调用修改实例的非const成员函数很有用。
例如,在单独的线程中调用QByteArray::split()(一个const成员函数)是这样做的:
// call 'QList<QByteArray> QByteArray::split(char sep) const' in a separate threadQByteArray bytearray = "hello world";QFuture<QList<QByteArray> > future = QtConcurrent::run(bytearray, &QByteArray::split, ',');...QList<QByteArray> result = future.result();
调用非const成员函数是这样做的:
// call 'void QImage::invertPixels(InvertMode mode)' in a separate threadQImage image = ...;QFuture<void> future = QtConcurrent::run(&image, &QImage::invertPixels, QImage::InvertRgba);...future.waitForFinished();// At this point, the pixels in 'image' have been inverted
2. 使用Lambda函数
调用lambda函数是这样做的:
QFuture<void> future = QtConcurrent::run([=]() {// Code in this block will run in another thread});...
相关文章:
Qt扫盲-Qt Concurrent概述
Qt Concurrent概述 一、概述二、Concurrent Map 和 Map- reduce1. 并发 Map2. 并发 Map-Reduce3. 其他API特性1. 使用迭代器而不是Sequence3. 阻塞变量4. 使用成员函数5. 使用函数对象6. 包装接受多个参数的函数 三、Concurrent Filter and Filter-Reduce1. 并发过滤器2. 并发F…...

c语言用json解析库(jansson)检测字符串是否是json格式的数据
C语言检测字符串是否是json格式的数据,可以用jansson库检测,也可以用cjson库来校验。但是若数据格式有问题,jansson可以指出哪里有错误,cjson无法指出。 下面就演示C语言如何使用jansson库检测字符串是否是json格式的数据。 1.下载…...
我再记录一个bug
项目场景: 提示:这里简述项目相关背景: 例如:项目场景:示例:通过蓝牙芯片(HC-05)与手机 APP 通信,每隔 5s 传输一批传感器数据(不是很大) 问题描述 提示:这里描述项目中遇到的问题࿱…...

AJAX: 对话框大全
AJAX:$.ajax({url: "/admin/cutting/getDataWeek",type: "GET",data:{},dataType:json,success: function (res) {if (res.code 1) {}},error:function (error) {console.log(请求失败);console.log(error);}}); $(.sub).unbind(click).click(funct…...

LeetCode讲解篇之40. 组合总和 II
文章目录 题目描述题解思路题解代码 题目描述 题解思路 按升序排序candidates,然后遍历candidates,目标数减去当前candidates的数,若该结果小于0,因为candidates的元素大于0,所以后续不会再出现让计算结果等于0的情况…...

RK3568平台 GPIO子系统框架
一.gpio 子系统简介 gpio 子系统顾名思义,就是用于初始化 GPIO 并且提供相应的 API 函数,比如设置 GPIO为输入输出,读取 GPIO 的值等。gpio 子系统的主要目的就是方便驱动开发者使用 gpio,驱动 开发者在设备树中添加 gpio 相关信…...

buu第五页 wp
[RootersCTF2019]babyWeb 预期解 一眼就是sql注入,发现过滤了 UNION SLEEP " OR - BENCHMARK盲注没法用了,因为union被过滤,堆叠注入也不考虑,发现报错有回显,尝试报错注入。 尝试: 1||(updatex…...

【论文阅读】以及部署BEVFusion: A Simple and Robust LiDAR-Camera Fusion Framework
BEVFusion: A Simple and Robust LiDAR-Camera Fusion Framework BEVFusion:一个简单而强大的LiDAR-相机融合框架 NeurIPS 2022 多模态传感器融合意味着信息互补、稳定,是自动驾驶感知的重要一环,本文注重工业落地,实际应用 融…...

N——>BatchSize 数据维度理解和处理(chun, cat, squeeze, unsqueeze)
数据处理之N——>BatchSize N——>batch_size train_data TensorDataset(torch.Tensor(x_train).double(), torch.Tensor(y_train).double()) train_loader DataLoader(train_data, batch_sizeargs.bs, shuffleTrue, drop_lastTrue) for batch_idx, (inputs, results…...
【编解码格式】AV1
AV1 AOMedia Video 1(简称AV1)是一个开放、免专利的视频编码格式,专为通过网络进行流传输而设计。它由开放媒体联盟(AOMedia)开发,目标是取代其前身VP9[2],该联盟由半导体企业、视频点播供应商…...

SLAM ORB-SLAM2(6)系统对象
SLAM ORB-SLAM2(6)系统对象 1. 封装2. 成员变量2.1. 核心数据2.2. 三个对象2.3. 三个线程2.4. 跟踪状态3. 成员函数4. 构造函数5. 数据驱动接口1. 封装 在 《SLAM ORB-SLAM2(5)例程了解》 了解到创建了一个 ORB_SLAM2::System 类型的对象 然后不断的把数据供给该对象就可以…...

03、Python 字符串高级用法
目录 Python 字符串高级用法转义字符字符串格式化序列相关的方法大小写相关的方法dir 可以查看某个类的所有方法删除空白查找、替换相关方法 Python 字符串高级用法 转义字符 字符串格式化 序列相关的方法 字符串本质就是由多个字符组成,字符串的本质就是不可变序…...

armbian安装gcc、g++
文章目录 安装GCC安装G 安装GCC 打开终端,更新软件包列表: sudo apt update安装GCC: sudo apt install gcc如果需要安装特定版本的GCC,可以使用以下命令: sudo apt install gcc-<version> # sudo apt install g…...

Linux多线程服务端编程:使用muduo C++网络库 学习笔记 第二章 线程同步精要
并发编程有两种基本模型,一种是message passing,另一种是shared memory。在分布式系统中,运行在多台机器上的多个进程的并行编程只有一种实用模型:message passing。在单机上,我们也可以照搬message passing作为多个进…...

中间件安全-CVE复现WeblogicJenkinsGlassFish漏洞复现
目录 服务攻防-中间件安全&CVE复现&Weblogic&Jenkins&GlassFish漏洞复现中间件-Weblogic安全问题漏洞复现CVE_2017_3506漏洞复现 中间件-JBoos安全问题漏洞复现CVE-2017-12149漏洞复现CVE-2017-7504漏洞复现 中间件-Jenkins安全问题漏洞复现CVE-2017-1000353漏…...

辅助驾驶功能开发-功能规范篇(16)-2-领航辅助系统NAP-HMI人机交互
书接上回 2.3.7HMI人机交互 2.3.7.1显示 (1)图标 序号 图标状态 (图形、颜色供参考) 含义说明 备注 1 辅助驾驶功能READY (允许激活) 2 辅助驾驶功能激活 3 辅助驾驶系统故障 4...

[计算机入门] 应用软件介绍(娱乐类)
3.21 应用软件介绍(娱乐类) 3.21.1 音乐:酷狗 音乐软件是一类可以帮助人们播放、管理和发现音乐的应用程序。它们提供了丰富的音乐内容,用户可以通过搜索、分类浏览或个性化推荐等方式找到自己喜欢的歌曲、专辑或艺术家。音乐软件还通常支持创建和管理…...

SL8541 android系统环境+编译
1.Ubuntu系统的安装 最好使用ubuntu18.0.4 2.工具环境包的安装 // 安装Android8.1源码编译环境 sudo apt-get install openjdk-8-jdk --------------ok sudo apt-get install libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-dev g-multilib --------------ok sudo…...

【苍穹外卖 | 项目日记】第八天
前言: 昨天晚上跑完步回来宿舍都快停电了,就没写项目日记,今天补上 目录 前言: 今日完结任务: 今日收获: 引入百度地图接口: 引入spring task ,定时处理异常订单: …...

概念解析 | 毫米波雷达与计算机视觉的融合
注1:本文系“概念解析”系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:毫米波雷达与计算机视觉的融合。 毫米波雷达与计算机视觉的融合 Sensors | Free Full-Text | MmWave Radar and Vision Fusion for Object Detection in Autonomous Driving: A …...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...

19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...

Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...

华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...

python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...