在 C++ 中创建和使用线程

Create and use threads in C++

对于大学,我必须编写一个像 space Invaders.

这样的程序

现在我们要为主要的spaceShip编写"bullet"-Class来发射子弹。 每个项目符号都必须创建自己的线程。线程必须执行 run 方法。

Bullet.hpp

ifndef BULLET_HPP_
define BULLET_HPP_

include "TriangleMesh.hpp"

include <GL/glu.h>
include <GL/glut.h>

include <thread>
include <chrono>

namespace asteroids
{
    class Bullet : public TriangleMesh
    {
        public:
        /**
         * @brief Contructor. Build a bullet on the given Fighter's
         *                      position. The bullet will move on the
         *                      given axis.
         * @param   fighter_position   Position of the fighter that shoots this bullet
         * @param   fighter_axis   Axis the bullet will move on
         */
        Bullet(Vertex<float> fighter_position, Vertex<float> fighter_axis);
        ~Bullet();
        /**
         * @brief Moves the bullet until it's lifetime is over.
         */
        void run();
        /**
         * @brief Starts bullet movement
         */
        void start();
        /*
         * @brief Stops bullet movement
         */
        void stop();
        /**
         * @brief Renders the bullet via glutSolidSphere.
         */
        void render();
        /**
         * @brief Returns the status of this bullet.
         * @return false, if the bullet's lifetime is over and true otherwise
         */
        bool isAlive();
        private:
        // Lifetime, i.e., how many timesteps the bullet visible
        static const int m_lifetime = 9000;
        // True, if the bullet's lifetime isn't over yet
        bool m_alive;
        // Flight direction of the bullet
        Vertex<float> m_fighterAxis;
        //position of the fighter
        Vertex<float> m_fighterPosition;
        static void staticRun(Bullet * bullet);
        bool isRunning;
        /// TODO: ADD TIMING AND THREAD FUNCTIONALITY
        void stopThread();
        void startThread();
        void sleep(int n)
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(n));
        }
    };
} // namespace asteroids

#endif /* BULLET_HPP_ */

/**
* Bullet.cpp
*
*/

BULLET.CPP

#include "Bullet.hpp"
using namespace std;

namespace asteroids
{
    Bullet::Bullet(Vertex<float> fighter_position, Vertex<float> fighter_axis)
        : m_alive(true)
    {
        // TODO: Implement Ctor logic
        m_fighterAxis = fighter_axis;
        m_fighterPosition = fighter_position;
        m_position = fighter_position;
        startThread();
    }
    void Bullet::stopThread()
    {
        currentThread->join();
    }
    //creates a static-member option for starting the thread with an argument.
    void Bullet::staticRun(Bullet* bullet)
    {
        bullet->run();
    }
    //Logic to create and start a Thread with out static function to execute
    void Bullet::startThread()
    {
        Bullet* bullet = this;
        std::thread t1(&Bullet::staticRun, bullet);
        currentThread = t1; //Here i wanted to set the pointer equal the existing thread
        //But compiler says that i cant convert a thread type to a                           //pointer type
    }

    Bullet::~Bullet() {}
    bool Bullet::isAlive()
    {
        return m_alive;
    }

    void Bullet::stop()
    {
        m_alive = false;
    }

    void Bullet::start()
    {
        if (isAlive())
        {
            // TODO: Implement thread start logic
            startThread();
        }
    }

    void Bullet::run()
    {
        Vertex<float> move = Vertex<float>(1, 1, 1);
        for (int i = 0; i < m_lifetime; i++)
        {
            m_position = m_fighterAxis + move;
            render();
            sleep(1000);
            //this->sleep(1000);
        }
        stop();
    }

    void Bullet::render()
    {
        // Compute transformation matrix
        computeMatrix();
        // Push old transformation of the OpenGL matrix stack and
        // start rendering the bullet in according to the
        // internal transformation matrix
        glPushMatrix();
        glMultMatrixf(m_transformation);
        glutSolidSphere(10, 16, 16);
        // Pop transformation matrix of this object
        // to restore the previous state of the OpenGL
        // matrix stack
        glPopMatrix();
    }
} // namespace asreroids

现在我的问题是:在单独的方法中创建线程并创建一个保存它的指针是否正确?

或者如果没有线程父class,您将如何实现线程逻辑?

谢谢大家的帮助,如果排版不对请见谅 post 在此表扬一下,这是我第一次 post ^^

拥有太多 "bullet" 个对象并且每个 运行 它都是自己的线程,这将使以后在需要时更难调试....可以做到这一点的一种方法是通过使用 ThreadPool 模式.. 单个线程池不仅可以用于子弹,还可以用于系统中的其他实体......您将拥有所有线程的中央存储库,并且可以在需要时监视它们.. .

https://codereview.stackexchange.com/questions/40536/simple-thread-pool-in-c

    Bullet* bullet = this;
    std::thread t1(&Bullet::staticRun, bullet);
    currentThread = t1;

就上面的代码而言,currentThread 是 class 成员吗?我没有使用太多的 c++11 线程,但是 std::thread t1(&Bullet::静态运行,子弹);一旦方法执行完成就超出范围??

您应该将函数绑定到您要传递的变量,在这种情况下,我建议您将它绑定到您正在创建的实例,然后是函数将接收的参数,通常是您将该函数声明为成员函数,然后将实例绑定到它,然后将它传递给您正在创建的线程。

我们在下面使用互斥锁来保护 running 布尔值免受多线程访问。您应该使用互斥锁来保护可以被多个线程访问的变量。

currentThread.join(); 等待线程完成。

#include <thread>
#include <mutex>
#include <chrono>



class Bullet{

public:
    void startThread(){
        currentThread = std::thread(std::bind(&Bullet::run, this));
    }


    void run(){
        while (isRunning()){
            std::this_thread::sleep_for(std::chrono::milliseconds(200));

            //Do something.
        }
    }

    void Bullet::stopThread()
    {
        runMutex.lock();
        running = false;
        runMutex.unlock();

        currentThread.join();
    }

    bool isRunning(){ 
        bool isRunning = false;
        runMutex.lock(); 
        isRunning = running;
        runMutex.unlock(); 
        return isRunning;
    }

private:
    std::thread currentThread;
    std::mutex runMutex;
    bool running;
};





int main()
{

    Bullet bullet;
    bullet.startThread();


    bullet.stopThread();

    return 0; //return.
}