带有成员函数的多线程和带有参数的构造函数

时间:2016-01-12 05:15:26

标签: c++ c++11 shared-ptr boost-thread

我有一种情况需要实例化一个boost :: threads的向量来解决以下问题:

我有一个名为Instrument的类来保存符号信息,如下所示:

class Instrument
{
    public:
    Instrument(StringVector symbols, int i);
    virtual ~Instrument();
    const Instrument& operator= (const Instrument& inst)
    {
        return *this;
    }
    String GetSymbol() { return Symbol_; }
    LongToSymbolInfoPairVector GetTS() { return TS_; }
    bool OrganiseData(TimeToSymbolsInfoPairVector& input, int i);
    static int getRandomNumber(const int low, const int high);
    static double getProbability();
    bool ConstructNewTimeSeries(const int low, const int high);
    bool ReconstructTimeSeries(TimeToSymbolsInfoPairVector& reconstructeddata, int i);

private:
    LongToSymbolInfoPairVector TS_;
    String Symbol_;
    const int checkWindow_;
    String start_, end_;
    long numberofsecsinaday_;
    static std::default_random_engine generator_;
};

此类将包含与符号数一样多的对象。这些符号应在另一个类中进行分析以获得进一步的工作,其构造函数接受上述Instrument类的向量,如下所示。

class Analysis
{
public:
    Analysis(std::vector<Instrument>::iterator start, std::vector<Instrument>::iterator end);
    virtual ~Analysis();
    bool buildNewTimeSeries(TimeToSymbolsInfoPairVector& reconstructeddata);
    bool printData(TimeToSymbolsInfoPairVector& reconstructeddata);

private:
    std::vector<Instrument> Instruments_;
};

现在我想多线程化这个过程,这样我就可以分离出每个线程7个符号并产生4个线程。

以下是更新的主页。

std::vector<Instrument>::iterator block_start = Instruments.begin();
int first = 0, last = 0;
for (unsigned long i=0; i<MAX_THREADS; i++)
{
    std::vector<Instrument>::iterator block_end = block_start;
    std::advance(block_end, block_size);
    last = (i+1)*block_size;
    Analysis* analyzed = new Analysis(block_start, block_end /*first, last*/);
    analyzed->setData(output, first, last);
    threads.push_back(std::thread(std::bind(&Analysis::buildNewTimeSeries, std::ref(*analyzed))));
    block_start = block_end;
    first = last;        
}

for (int i=0; i<MAX_THREADS; i++)
{
    (threads[i]).join();
}

这显然是不正确的,虽然我知道如何实例化一个线程的构造函数来传递一个类构造函数一个参数或一个成员函数一个参数,但是当我的目的是:我似乎面临一个问题: a)将类Analysis的构造函数传递给vector和的子集 b)调用buildNewTimeSeries(TimeToSymbolsInfoPairVector&amp; reconstructeddata) 对于4个线程中的每个线程,然后再加入它们。

有人可以建议一个巧妙的方法吗?

1 个答案:

答案 0 :(得分:0)

将资源向量(例如std :: vector)划分为有限数量的线程的最佳方法是使用名为 threadpools 的多线程设计范例。在c ++中没有标准的线程池,因此您可能必须自己构建一个(或使用开源库)。您可以在这里查看众多优秀的开源实现之一: - https://github.com/progschj/ThreadPool

现在,我不会使用线程池,但只会给你一些建议,以帮助你修复你的问题而不修改你的核心功能/想法。

在main中,您使用 new 动态创建向量,并通过取消引用指针传递向量的引用。分析*分析=新的。我理解你的想法是在main和thread函数中使用相同的向量分析*。在我看来,这不是一个好的设计。有一种更好的方法可以做到。

而不是使用std :: thread使用 std :: async。 std :: async创建任务而不是线程。使用异步使用任务有很多优点。我不想通过描述线程/任务来做出这个很长的答案。但是,在您的情况下直接帮助您的任务的一个主要优点是它允许您将任务中的值(称为future)返回到主函数。

不要重写主函数async,调整代码如下,

  • 不要使用new动态创建矢量,而只是创建一个 本地向量,只需使用std :: move移动向量即可 在调用异步时。
  • 修改Analysis :: buildNewTimeSeries以接受右值引用。
  • 使用rvalue vector
  • 编写用于分析的构造函数
  • 然后,任务将在本地修改此向量 将此向量返回到main函数。
  • 在调用异步时存储异步的返回值 调用向量&lt;未来&lt; objectType&gt; &GT;
  • 使用async启动所有任务后,可以在此未来向量的每个元素上调用.get()。
  • 此.get()方法将返回修改并返回的向量 线。
  • 将这些返回的向量合并到最终结果向量中。

通过将向量从main移动到线程然后将其返回,您只允许一个所有者对向量进行独占访问。因此,在将其移动到线程后,您无法从main访问该向量。这与您的实现形成对比,其中main函数和线程函数都可以访问通过引用线程传递的新创建的向量。