QT高级线程API总结(二)QtConcrrent::map

目录

 

1、Header: #include

2、qmake: QT += concurrent

3、 详情描述

4 number functions

4.1 QtConcurrent::mapped

4.2 QtConcurrent::map

4.3 QtConcurrent::mappedReduced

4.4 QtConcurrent::blockingMap

4.5 QtConcurrent::blockingMapped

4.6 QtConcurrent:: blockingMappedReduced

5、API附加特征

5.1 使用迭代器代替容器

5.2 阻塞变量

5.3 使用成员函数

5.4 使用函数对象

5.5 多个函数参数

6、代码示例

6.1  QtConcurrent::mapped()

6.2  QtConcurrent::map()

6.3 QtConcurrent::mappedReduced()


1、Header: #include <QtConcrrent>

2、qmake: QT += concurrent

3、 详情描述

QtConcurrent::map(), QtConcurrent::mapped() 和 QtConcurrent::mappedReduced() 函数在一个序列中(例如:QList 或者 QVector )并行的运行计算。

QtConcurrent::map() 在原地修改序列;

QtConcurrent::mapped() 返回一个包含修改内容的新序列;

QtConcurrent::mappedReduced() 返回单个结果;

这些函数都是Qt并发框架的一部分。

上面的每一个函数都有一个阻塞变量,它返回最终结果,而不是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>和QImage).

4 number functions

4.1 QtConcurrent::mapped

QtConcurrent::mapped() 接受一个输入序列和映射函数。然后对序列中的每个项调用这个映射函数,并返回一个包含映射函数返回值的新序列。

必须是如下格式:

U function(const T &t);

U和T可以是任意类型(可以相同),但是T必须与存储在序列中的类型匹配。函数返回修改或者映射的内容。如下所示:

QImage scaled(const QImage &image)

{

         return image.scaled(100, 100);

}

QList<QImage> images = ...;

QFuture<QImage> thumbnails = QtConcurrent::mapped(images, scaled);

返回结果可以通过QFuture获得。有关如何在应用中使用更多的QFuture信息,可以参考QFuture和QFutureWatcher文档。

如果想要修改一个序列,可使用QtConcrrent::map()。

4.2 QtConcurrent::map

使用 QtConcurrent::map() 可以修改一个序列,map()函数必须是以下形式:

U function(T &t);

注意:这里不会使用函数的返回值和返回类型。

使用map()类似于使用mapped():

void scale(QImage &image)

{

   image = image.scaled(100, 100);

}

QList<QImage> images = ...;

QFuture<void> future = QtConcurrent::map(images, scale);

由于容器内容已被修改,QtConcrrent::map()不会通过QFuture返回任何结果。但是,仍然可以使用QFuture和QFutureWatcher来监视映射状态。

4.3 QtConcurrent::mappedReduced

QtConcurrent::mappedReduced() 类似于 QtConcurrent::mapped(),但不是返回一个带有新结果的序列,而是使用reduce函数讲结果组合成一个单独的值。

函数模版:

V function(T &result, const U &intermediate)

T是最终的结果类型,U是映射函数的返回类型。注意,reduce函数的返回值和返回类型没有被使用。

如下方式调用:
 

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函数,并且会将中间值合并到结果变量中。QtConcrrent::mappedReduced()保证每次只有一个线程会调用reduce,所以不需要使用互斥锁来锁定结果变量。QtConcurrent::ReduceOptions枚举类型提供一个控制顺序的方法。QtConcurrent::UnorderedReduce是默认的, 其顺序未定义, 而 QtConcurrent::OrderedReduce 确保按原始序列输出。

4.4 QtConcurrent::blockingMap

void QtConcurrent::blockingMap(Sequence &sequence, MapFunction function)

对每个项按顺序调用函数一次。该函数将向项传递一个引用,以便对项所做的任何修改都将依次显示。

注意:这个函数将阻塞直到序列中的所有项都被处理完。

void QtConcurrent::blockingMap(Iterator begin, Iterator end, MapFunction function)

从头到尾对每个项调用函数一次。该函数将向该元素传递一个引用,以便对该元素所做的任何修改都将出现在迭代器所属的序列中。

注意:这个函数将会阻塞,直到迭代器到达正在处理的序列的末尾。

4.5 QtConcurrent::blockingMapped

T QtConcurrent::blockingMapped(const Sequence &sequence, MapFunction function)

对序列中的每个项调用函数一次,并返回包含结果的序列。结果的类型将匹配我的MapFunction返回的类型。

注意:这个函数将阻塞直到序列中的所有项都被处理完。

T QtConcurrent::blockingMapped(ConstIterator begin, ConstIterator end, MapFunction function)

对每个条目从头到尾调用函数一次,并返回一个带有结果的容器。将容器类型指定为a模板参数,如下所示:

QList<int> int = QtConcurrent::blockingMapped<QList<int> >(beginIterator, endIterator, fn);

注意:这个函数将会阻塞,直到迭代器到达正在处理的序列的末尾。

4.6 QtConcurrent:: blockingMappedReduced

T QtConcurrent::blockingMappedReduced(const Sequence &sequence, MapFunction mapFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions = UnorderedReduce | SequentialReduce)

对每个项按顺序调用mapFunction一次。每个mapFunction的返回值被传递给reduceFunction。

注意,当mapFunction被并发调用时,每次只有一个线程会调用reduceFunction。reduceFunction的调用顺序由reduceOptions决定。

注意:这个函数将阻塞直到序列中的所有项都被处理完。

T QtConcurrent::blockingMappedReduced(ConstIterator begin, ConstIterator end, MapFunction mapFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions = UnorderedReduce | SequentialReduce)

对每个条目从头到尾调用mapFunction一次。每个mapFunction的返回值被传递给reduceFunction。

注意,当mapFunction被并发调用时,每次只有一个线程会调用reduceFunction。reduceFunction的调用顺序没有定义。

注意:这个函数将会阻塞,直到迭代器到达正在处理的序列的末尾。

5、API附加特征

5.1 使用迭代器代替容器

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);

5.2 阻塞变量

QList<QImage> images = ...;

// 每次调用都会被阻塞,直到调用完成

QList<QImage> future = QtConcurrent::blockingMapped(images, scaled);

QtConcurrent::blockingMap(images, scale);

QImage collage = QtConcurrent::blockingMappedReduced(images, scaled, addToCollage);

注意:上述的结果类型不是 QFuture 对象,而是实际结果类型(在这种情况下,是 QList<QImage>和 QImage)。

5.3 使用成员函数

QtConcurrent::map()、QtConcurrent::mapped() 和 QtConcurrent::mappedReduced() 接受成员函数的指针,成员函数类类型必须与存储在序列中的类型匹配:

// Squeeze all strings in a QStringList.

QStringList strings = ...;

QFuture<void> squeezedStrings = QtConcurrent::map(strings, &QString::squeeze);

// 交换 images 列表中图片所有像素的 rgb 值

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() 时,可以自由地混合使用正常函数和成员函数:

// 可以使用 QtConcurrent::mappedReduced() 混合正常函数和成员函数

// 计算字符串列表的平均长度

extern void computeAverage(int &average, int length);

QStringList strings = ...;

QFuture<int> averageWordLength = QtConcurrent::mappedReduced(strings, &QString::length, computeAverage);

// 创建一个列表中所有图像颜色分布的集合

extern int colorDistribution(const QImage &string);

QList<QImage> images = ...;

QFuture<QSet<int> > totalColorDistribution = QtConcurrent::mappedReduced(images, colorDistribution, QSet<int>::insert);

5.4 使用函数对象

QtConcurrent::map()、QtConcurrent::mapped() 和 QtConcurrent::mappedReduced() 接受函数对象,可用于向函数调用添加状态。result_type typedef 必须定义结果函数调用操作符的类型:

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))

5.5 多个函数参数

如果你想要使用带多个参数的map函数,你可以使用Lamada函数或者std::bind()将其转化为带一个参数的函数。

例如:我们将使用

QImage QImage::scaledToWidth(int width, Qt::TransformationMode) const;

scaledToWidth有三个参数(包含this指针),不能直接与QtConcrrent::mapped()一起使用,因为QtConcrrent::mapped()期望一个只有一个参数的函数。如要在QtConcrrent::mapped()中使用QImage::scaledToWidth(),我们必须为宽度和转换模式提供一个值:

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);

6、代码示例

6.1  QtConcurrent::mapped()

    extern int func(const int &arg){
        return arg+1;
    };

    QList<int> list;
    list << 1 << 2 << 3 << 4 << 5 << 6;
    QFuture<int> future = QtConcurrent::mapped(list, func);
    qDebug() << "list: " << list << ", future:" << future.results();
    //输出: list:  (1, 2, 3, 4, 5, 6) , future: (2, 3, 4, 5, 6, 7)

6.2  QtConcurrent::map()

    QList<int> list;
    list << 1 << 2 << 3 << 4 << 5;
    qDebug() << "start list: " << list ;
    QFuture<void> future = QtConcurrent::map(list, func);
    QFutureWatcher<void> *watcher = new QFutureWatcher<void>(this);
    watcher->setFuture(future);
    connect(watcher, &QFutureWatcher<void>::finished, [=](){
        qDebug() << "finished list: " << list ;
    });
    //输出:
    //start list:  (1, 2, 3, 4, 5)
    //finished list:  (2, 3, 4, 5, 6)

6.3 QtConcurrent::mappedReduced()

    extern int func(const int &arg){
        return arg + 1;
    };
    
    void addCollage(int &result, const int &arg)
    {
        if(result < arg)
            result = arg;
    }
    
    QList<int> list;
    list << 1 << 2 << 3 << 4 << 5;
    QFuture<int> collage = QtConcurrent::mappedReduced(list, func, addCollage);

    collage.waitForFinished();
    qDebug() << collage.result();  //6

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值