0

I am supposed to create 3 threads first will print 'A' every 3 seconds, second 'B' every 4 seconds and 'C' every 5 seconds.

I did it like that but they change their order durign printing and it is suspicous. But I think that in 9th second they can mix... and its fine. Please post yuur opinion.

public class MyThread extends Thread {

    static int ID;
    int id;

    public MyThread() {
        id = ID++;
    }

    public synchronized void run() {
        char character = (char) (65 + id);
        while (true) {
            System.out.println(character);
            try {
                Thread.sleep(3000 + id * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        new MyThread().start();
        new MyThread().start();
        new MyThread().start();
    }
}

Output:

A
B
C
A
B
C
A
B
A
C
B
A
.......
Yoda
  • 16,053
  • 60
  • 184
  • 315

2 Answers2

2

There is a general issue with using sleep; it schedules between the end of one task the the beginning of the next. Not between the beginning of two tasks.

So, every time your tasks run they fall a little off the time you wanted them to run.

This is generally why sleep is not used for scheduling tasks as a specific rate.

As @Joachim points out, your output looks fine. Here is a quick calculation of when each thread should print:

Timeline spreadsheet

However I would strongly recommend that you use a ScheudledExecutorService as below:

public static void main(final String[] args) throws Exception {
    final ScheduledExecutorService ses = Executors.newScheduledThreadPool(3);
    final class Work implements Runnable {

        private final String name;

        public Work(String name) {
            this.name = name;
        }

        @Override
        public void run() {
            System.out.println(name);
        }
    }
    ses.scheduleAtFixedRate(new Work("A"), 0, 3, TimeUnit.SECONDS);
    ses.scheduleAtFixedRate(new Work("B"), 0, 4, TimeUnit.SECONDS);
    ses.scheduleAtFixedRate(new Work("C"), 0, 5, TimeUnit.SECONDS);
    ses.schedule(new Runnable() {

        @Override
        public void run() {
            ses.shutdown();
        }
    }, 1, TimeUnit.MINUTES);
    ses.awaitTermination(1, TimeUnit.DAYS);
}

With a few Java 8 lambdas:

public static void main(final String[] args) throws Exception {
    final ScheduledExecutorService ses = Executors.newScheduledThreadPool(3);
    ses.scheduleAtFixedRate(() -> System.out.println("A"), 0, 3, TimeUnit.SECONDS);
    ses.scheduleAtFixedRate(() -> System.out.println("B"), 0, 4, TimeUnit.SECONDS);
    ses.scheduleAtFixedRate(() -> System.out.println("C"), 0, 5, TimeUnit.SECONDS);
    ses.schedule(() -> ses.shutdown(), 1, TimeUnit.MINUTES);
    ses.awaitTermination(1, TimeUnit.DAYS);
}
Boris the Spider
  • 57,395
  • 6
  • 106
  • 161
1

Style issues discussed in the comments aside, the output you're showing looks correct;

A    0 seconds, thread start
B    0 seconds, thread start
C    0 seconds, thread start
A    3 seconds
B    4 seconds
C    5 seconds
A    6 seconds (2*3)
B    8 seconds (2*4)
A    9 seconds (3*3)
C   10 seconds (2*5)
B   12 seconds (3*4)
A   12 seconds (4*3)
...
Joachim Isaksson
  • 170,943
  • 22
  • 265
  • 283