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

Multithreading with member functions and constructor carrying argument(s)

本文关键字:构造函数 多线程 参数 成员 函数      更新时间:2023-10-16

我有一种情况,需要实例化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_;
};

此类的对象数量与符号数量一样多。这些符号应在另一个类Analysis中访问,以进行进一步的工作,其构造函数接受上述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个线程。

以下是更新后的main。

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的构造函数向量的子集和b) 调用buildNewTimeSeries(TimeToSymbolsInfoPairVector&rebuildeddata)对于4个线程中的每一个线程,然后稍后将它们连接起来。

有人能提出一个巧妙的方法吗?

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

现在,我不打算使用线程池,只会给你几个建议,帮助你在不修改核心功能/想法的情况下解决问题。

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

不使用std::thread,而是使用std::asyncstd::async创建任务,而不是线程。通过使用async来使用任务有许多优点。我不想通过描述线程/任务来让这个问题成为一个冗长的答案。但是,任务的一个主要优点是,它可以让您将任务中的值(称为future)返回到主函数,这对您的情况有直接帮助。

不可以重写你的主要函数async,按如下方式调整你的代码,

  • 不要使用new动态创建矢量,只需创建局部向量,然后使用std::move将向量移动到任务同时调用async
  • 修改Analysis::buildNewTimeSeries以接受右值引用
  • 编写一个使用右值向量进行分析的构造函数
  • 然后,任务将局部修改此矢量,然后将此向量返回到main函数
  • 调用async时存储async的返回值向量<future<对象类型>>
  • 在使用async启动所有任务后,可以对这个未来向量的每个元素调用.get()
  • 此.get()方法将返回从螺纹
  • 将这些返回的向量合并到最终结果向量中

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