2

I am currently working on a project where I am to have essentially 10 threads that are "sleeping". At random one of these 10 threads is to "wake up" and start doing some work. I just want to see if I am headed in the right direction. So should I just create each instance of the thread for instance.

Thread thread0 = new Thread(new doWork());
...
Thread thread9 = new Thread(new doWork());

and just not start them and then when they are to "wake" just call the start() method on the particular thread..

or should I start each thread but have them wait() until I call the notify() method?

or should I start the thread and use sleep() and then call the interrupt() method?

Which approach seems to be better and why?

Any insight is greatly appreciated.

edit Will this be acceptable??

import java.util.Random;

public class Client {

private static Thread [] clients = new Thread[10];

public static void main(String[] args){

    createClients();
    randomWake();

}// end main()

static void createClients(){

    Thread client0 = new Thread(new ClientThread(0));
    clients[0] = client0;
    Thread client1 = new Thread(new ClientThread(1));
    clients[1] = client1;
    Thread client2 = new Thread(new ClientThread(2));
    clients[2] = client2;
    Thread client3 = new Thread(new ClientThread(3));
    clients[3] = client3;
    Thread client4 = new Thread(new ClientThread(4));
    clients[4] = client4;
    Thread client5 = new Thread(new ClientThread(5));
    clients[5] = client5;
    Thread client6 = new Thread(new ClientThread(6));
    clients[6] = client6;
    Thread client7 = new Thread(new ClientThread(7));
    clients[7] = client7;
    Thread client8 = new Thread(new ClientThread(8));
    clients[8] = client8;
    Thread client9 = new Thread(new ClientThread(9));
    clients[9] = client9;

    for(int i = 0; i < clients.length; i++)
        clients[i].start();

}// end createClients()

static void randomWake(){

    Random rand = new Random();
    int randomNumber = rand.nextInt(10);

    clients[randomNumber].interrupt();

}// end randomWake()

static class ClientThread implements Runnable{

    private int clientNumber;

    public ClientThread(int clientNumber){
        this.clientNumber = clientNumber;
    }// end ClientThread(int clientNumber)

    public void run(){
        while(!Thread.interrupted()){}
        System.out.println("Client " + clientNumber + " is awake!");
    }// end run()

}// end class ClientThread

}// end class Client

Meekso
  • 75
  • 5

4 Answers4

0

In case there is a maximum amount of sleep time

You probably will need to implement the following Thread class:

public class DoWork extends Thread {

    public void run () {
        while(true) {
            Thread.Sleep((int) Math.floor(Math.random()*10000));
            //do some work
        }
    }

}

Where 10000 is the maximum time in milliseconds a thread should sleep.

In case there is no maximum amount of sleep time

You probably will need to implement the following Thread class:

public class DoWork extends Thread {

    public void run () {
        while(true) {
            Thread.Sleep(1);
            if(Math.random() < 0.005d) {
            //do some work
            }
        }
    }

}

where 0.005 is the probability of running the method a certain millisecond.


notify and wait are used to implement Semaphores: this are objects that prevent two threads to manipulate the same object at the same time (since some objects could end up in an illegal state).

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • Well I added a case where there is no maximum amount of sleep time. – Willem Van Onsem Apr 17 '14 at 15:12
  • well the way I have been doing threads for this particular class and all projects before hand I use `implements Runnable` .. so should I be using `extends Threads` to make them sleep correctly? – Meekso Apr 17 '14 at 15:14
  • No, `Thread.Sleep` is a static method. You can even call it without using any threads/multiprogramming. It is quite confusing it is implemented there anyway. – Willem Van Onsem Apr 17 '14 at 15:16
  • Okay so basically the code you've provided will make every thread I create `sleep` upon start, how would I go about "waking" them up when I want them to perform a task? Will I be able to use `thread0.interrupt()` to make the thread stop sleeping? – Meekso Apr 17 '14 at 15:21
  • no, according to your question, the threads should wake at random moments. In case of event triggered tasks, you should use a *ThreadPool*. – Willem Van Onsem Apr 17 '14 at 15:22
  • You don't "wake up" a thread on demand. A thread can put itself to sleep using the ubiquitous Thread.sleep() method mentioned above. There is no guarantee of how long it will sleep or when and in what order sleeping threads wake up. It simply allows the OS to start working on another thread. Threads will already randomly be executed by the OS. – jgitter Apr 17 '14 at 15:46
0

How about using semaphores?

class DoWork extends Runnable {
    private final Semaphore semaphore;

    DoWork(Semaphore semaphore) {
        this.semaphore = semaphore;
    }

    @Override
    public void run() {
        while (true) {
            semaphore.acquire();
            //do some work
        }
    }
}

The main program can create an array of Semaphores, and an equal number of Threads running DoWork instances, so that each DoWork instance has its own semaphore. Each time the main program calls sema[i].release(), The run() method of the corresponding DoWork instance will "do some work" and then go back to waiting.

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57
0

It doesn't make much sense your answer, so not sure what you really want to achieve. But for what you describe you should put all threads waiting on the same lock and just notify the lock (it will awake only one randomly)

But as that doesn't make much sense, I guess you want to achieve something different.

Check this question regarding sleep vs wait: Difference between wait() and sleep()

Community
  • 1
  • 1
estani
  • 24,254
  • 2
  • 93
  • 76
0

Check this one. This is how I would solve it if I were not to use ThreadPooling (which is very correct as the others have said) and so that I can see how wait(),notify() and Thread.sleep() work. Checking google you will see (e.g. Thread.sleep and object.wait) that the mainly wait() and notify() are used for communication between threads and Thread.sleep is used so that you can pause your program.

-Part of this answer is based on this: http://tutorials.jenkov.com/java-concurrency/thread-signaling.html#missedsignals. You can check in the code to see the steps that you need to take (comment out some parts of the code) in order to make your program hang, so that you realize how to work with missed signals. The iterations needed for your program to hang are not fixed.

-The programm will run forever. You will need to work on it a bit in order to fix that.

Main

public class Main 
{
    public static void main(String[] args) 
    {
        Manager mgr = new Manager("manager");
        mgr.start();
    }
}

Manager

public class Manager extends Thread
{
    private final Object lock = new Object();
    private boolean wasSignalled = false;

    private DoWork[] workThreads = new DoWork[5];

    public Manager(String name){
        super(name);

        workThreads[0] = new DoWork(this,"work 0");
        workThreads[1] = new DoWork(this,"work 1");
        workThreads[2] = new DoWork(this,"work 2");
        workThreads[3] = new DoWork(this,"work 3");
        workThreads[4] = new DoWork(this,"work 4");
    }


    public void wakeUP()
    {
        synchronized (this.lock) {
            wasSignalled = true;
            this.lock.notify();
         }
    }
    public void pauseAndWait()
    {
        synchronized (this.lock) {
            if(!wasSignalled)
            {
                try {
                    this.lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //clear signal and continue running.
            wasSignalled = false;
         }
    }

    public void run () 
    {
        int i=0;
        while(true)
        {
            i++;
            System.out.println(" manager ...: "+i+" ");

            int choose = 0 + (int)(Math.random() * ((4 - 0) + 1));
            //choose=0; for debugginng

            if(!workThreads[choose].isAlive()){
                workThreads[choose].start();
            }
            else{
                workThreads[choose].wakeUP();
            }

            //wait to be notified by DoWork thread when its job
            //is done
            pauseAndWait();
        }
    }
}

DoWork

public class DoWork extends Thread
{
    private final Object lock = new Object();
    private boolean wasSignalled = false;

    private Manager managerThread;

    public DoWork(Manager managerThread,String name){
        super(name);

        this.managerThread=managerThread;
    }


    public void wakeUP()
    {
        synchronized (this.lock) {

            //check what happens without wasSignalled flag 
            //step #1: comment out wasSignalled = true;
            wasSignalled = true;    
            this.lock.notify();
         }
    }
    public void pauseAndWait()
    {
        synchronized (this.lock) {
            //check what happens without wasSignalled flag 
            //step #2: comment out the if block
            if(!wasSignalled)
            {
                try {
                    this.lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            //check what happens without wasSignalled flag 
            //step #3: comment out wasSignalled = false;

            //clear signal and continue running.
            wasSignalled = false;
         }
    }

    public void run () 
    {
        int i=0;
        while(true) 
        {           
            i++;

            try {
                System.out.print(this.getName()+" going to sleep ...: "+i+" ");

                //check what happens without wasSignalled flag 
                //step #4: put sleep time to Thread.sleep(0); 

                //simulate worker thread job
                Thread.sleep(1000); 
                System.out.println(" woke up ... ");
            } catch (InterruptedException e) {
                System.out.println(" worker thread: job simulation error:"+e);
            }

            //if worker thread job simulation is done (sleep for 4 times)
            //then suspend thread and wait to be awaken again
            if(i>4)
            {
                System.out.println(this.getName()+" notifying main  ...: "+i+" \n");
                i=0;
                managerThread.wakeUP();

                // thread does not get destroyed, it stays in memory and when the manager
                // thread calls it again it will wake up do its job again
                pauseAndWait();
            }
        }
    }
}
Community
  • 1
  • 1
zlinks
  • 1,037
  • 2
  • 16
  • 26