views:

97

answers:

1

My task is to simulate activity of couple of persons. Each of them has few activities to perform in some random time: fast (0-5s), medium(5-10s), slow(10-20s) and very slow(20-30s). Each person performs its task independently in the same time. At the beginning of new task I should print it's random time, start the task and then after time passes show next task's time and start it. I've written run() function that counts time, but now it looks like threads are done one after another and not in the same time or maybe they're just printed in this way.

public class People{
  public static void main(String[] args){
    Task tasksA[]={new Task("washing","fast"),
                new Task("reading","slow"),
                new Task("shopping","medium")};
    Task tasksM[]={new Task("sleeping zzzzzzzzzz","very slow"),
                new Task("learning","slow"),
                new Task("  :**   ","slow"),
                new Task("passing an exam","slow") };
    Task tasksJ[]={new Task("listening music","medium"),
                new Task("doing nothing","slow"),
                new Task("walking","medium")  };

    BusyPerson friends[]={ new BusyPerson("Alice",tasksA),
                           new BusyPerson("Mark",tasksM),
                           new BusyPerson("John",tasksJ)};

    System.out.println("STARTING.....................");
    for(BusyPerson f: friends)
      (new Thread(f)).start();
    System.out.println("DONE.........................");
  }
}

class Task {

    private String task;
    private int time;
    private Task[]tasks;

    public Task(String t, String s){
        task = t;    
        Speed speed = new Speed();
        time = speed.getSpeed(s);
    }

    public Task(Task[]tab){
        Task[]table=new Task[tab.length];
        for(int i=0; i < tab.length; i++){
            table[i] = tab[i];
        }
        this.tasks = table;
    }
}

class Speed {

    private static String[]hows = {"fast","medium","slow","very slow"};
    private static int[]maxs = {5000, 10000, 20000, 30000};

    public Speed(){
    }

    public static int getSpeed( String speedString){
        String s = speedString;
        int up_limit=0;
        int down_limit=0;
        int time=0;   
//get limits of time
        for(int i=0; i<hows.length; i++){
            if(s.equals(hows[i])){
                up_limit = maxs[i];
                if(i>0){
                    down_limit = maxs[i-1];
                }
                else{
                    down_limit = 0;
                }
            }
        }
//get random time within the limits
        Random rand = new Random();
        time = rand.nextInt(up_limit) + down_limit;

    return time;
    }

}

class BusyPerson implements Runnable {
    private String name;
    private Task[] person_tasks;
    private BusyPerson[]persons;

    public BusyPerson(String s, Task[]t){
        name = s;
        person_tasks = t;
    }

    public BusyPerson(BusyPerson[]tab){
        BusyPerson[]table=new BusyPerson[tab.length];
        for(int i=0; i < tab.length; i++){
            table[i] = tab[i];
        }
        this.persons = table;
    }

public void run() {
    int time = 0;
    double t1=0;

    for(Task t: person_tasks){
        t1 = (double)t.time/1000;
        System.out.println(name+" is...    "+t.task+"    "+t.speed+
                "   ("+t1+" sec)");
        while (time == t.time) {
            try {
                Thread.sleep(10);
            } catch(InterruptedException exc) {
                System.out.println("End of thread.");
                return;
            }
            time = time + 100;
        }
    }

}  
}

And my output :

STARTING.....................
DONE.........................
Mark is...    sleeping zzzzzzzzzz          very slow         (36.715 sec)
Mark is...    learning          slow         (10.117 sec)
Mark is...      :**             slow         (29.543 sec)
Mark is...    passing an exam          slow         (23.429 sec)
Alice is...    washing          fast         (1.209 sec)
Alice is...    reading          slow         (23.21 sec)
Alice is...    shopping          medium         (11.237 sec)
John is...    listening music          medium         (8.263 sec)
John is...    doing nothing          slow         (13.576 sec)
John is...    walking          medium         (11.322 sec)

Whilst it should be like this :

   STARTING.....................
   DONE.........................
   John is...    listening music     medium     (7.05 sec)
   Alice is...   washing     fast   (3.268 sec)
   Mark is...    sleeping zzzzzzzzzz     very slow  (23.71 sec)
   Alice is...   reading     slow   (15.516 sec)
   John is...    doing nothing   slow   (13.692 sec)
   Alice is...   shopping    medium     (8.371 sec)
   Mark is...    learning    slow   (13.904 sec)
   John is...    walking     medium     (5.172 sec)
   Mark is...    :**         slow   (12.322 sec)
   Mark is...    passing an exam        very slow   (27.1 sec)
+3  A: 

It seems like your waiting loop has the wrong termination condition, using time == t.time instead of time <= t.time. Also, it seems to increment by 100 instead of 10 in each iteration.

Also, you should reset time before each loop.

In other words, the loop

while (time == t.time) {
    try {
        Thread.sleep(10);
    } catch(InterruptedException exc) {
        System.out.println("End of thread.");
        return;
    }
    time = time + 100;
}

should probably be

time = 0;
while (time <= t.time) {
    try {
        Thread.sleep(10);
    } catch(InterruptedException exc) {
        System.out.println("End of thread.");
        return;
    }
    time += 10;
}

or use a for loop instead:

for (int time = 0; time <= t.time; time += 10) {
    try {
        Thread.sleep(10);
    } catch(InterruptedException exc) {
        System.out.println("End of thread.");
        return;
    }
}

However, there really isn't any reason to sleep in increments of 10 milliseconds. Also, Thread.sleep() may be inexact. It is better to try the entire period in one go, and check the clock afterwards.

long timeToWakeup = System.currentTimeMillis() + t.time;
long sleepMs = t.time;
while (sleepMs > 0) {
    try {
        Thread.sleep(sleepMs);
    } catch(InterruptedException exc) {
        System.out.println("End of thread.");
        return;
    }
    sleepMs = timeToWakeup - System.currentTimeMillis());
}
markusk
thanks, now it works perfectly.
owca