2
votes

I want to create a simple program that starts 5 threads that print "hello world! This is thread [thread number]".

Each print operation should be preceded by a random wait operation, to demonstrate that the threads are running concurrently. (The threads will print their message in a random order, as opposed to printing in order which would happen if the threads are running sequentially.)

Here is the code that should achieve this:

Poco::Thread thread[5];

class HelloRunnable: public Poco::Runnable
{
public:
    HelloRunnable(int arg)
    {
        n = arg;
    }

    int n;

    virtual void run()
    {
        usleep(rand()%100000);
        std::cout << "Hello, world! This is thread " << n << std::endl;
    }
};

int main() 
{
    for(int i=0; i<5; i++)
    {
        HelloRunnable runnable(i);
        thread[i].start(runnable);
    }

    for(int i=0; i<5; i++)
    {
        thread[i].join();
    }
    return 0;
}

However, at run time, this gives the error:

//pure virtual method called
//terminate called without an active exception
//The program has unexpectedly finished.

If instead, I put thread[i].join() inside the same for loop as thread[i].start(), then the program runs without error but it prints the threads in order. (Becuase join() waits until the thread has finished before moving on, hence the threads are executed sequentially and not concurrently.

How can I make the threads run concurrently and print out the message to the standard output as soon as cout is called?

2

2 Answers

1
votes

Since you create the objects inside the for loop their lifetime will end immediately after each iteration. This will cause issues. As the documentation for start() states:

Note that the given Runnable object must remain valid during the entire lifetime of the thread, as only a reference to it is stored internally.

You need to create the runnables in a way that keeps them alive outside the loop also.

0
votes

As Sami has said, the runnable was destroyed before the thread had finished. I removed the for loops and typed each line out explicitly. I also removed a thread as I can only run 4 threads without causing a crash. Finally, I created a separate runnable for each thread, as in the original code each thread was using the same one.

Poco::Thread thread[5];

class HelloRunnable: public Poco::Runnable
{
public:
    HelloRunnable(int arg)
    {
        n = arg;
    }

    int n;

    virtual void run()
    {
        //sleep for random length of time
        timeval t;
        gettimeofday(&t, NULL);
        srand(t.tv_usec * t.tv_sec);
        int uS = rand()%100000;
        usleep(uS);

        //print message
        std::cout << "Hello, world! This is thread " << n << " I slept for "<< uS << "uS" <<std::endl;
        return;
    }
};



int main()
{
    HelloRunnable runnable1(1);
    thread[1].start(runnable1);

    HelloRunnable runnable2(2);
    thread[2].start(runnable2);

    HelloRunnable runnable3(3);
    thread[3].start(runnable3);

    HelloRunnable runnable4(4);
    thread[4].start(runnable4);

    thread[1].join();
    thread[2].join();
    thread[3].join();
    thread[4].join();

    return 0;
}