0

I have View with some components handles. I can change color of label like this.
labelHandle.setForeground(Color.Blue);

I want to make text of this label blinking - the idea is that on the View I will have method blink(Boolean on) and if I call blink(true) the method will start new thread which will be class implementing Runnable.

loop of run() will be something like this

run() {
    for(;;) {
        if(finished == true) break;
        Thread.sleep(300);
        //this will do the blinking
        if(finished == true) break; //if durring sleep finish was called => end
        if(change) labelHandle.setForeground(Color.Blue);
        else labelHandle.setForeground(Color.Black);

        change = (change) ? false : true; //switch the condition 
    }
}

There will be some important points:

boolean finished - says if the thread is finished, the loop for bliniking 
void fihish() {this.finished = false;} //stops the thread job 
boolean change - switch for the collors, each end of loop switch this value, if its true set one color, if its false sets another => here we have blinking ... 

Until here its pretty clear how to do it. The main idea is make thread which will carry about the blinking.
In view I will call:

blink(true);
blink(false);

which will stars and stops the thread.
At one time only one view can be active, so I want have only one thread for blinking, which can be used with more views. The thread will be class implementing Runnable and should be Singleton to ensure, there will be only one thread.
Is it good idea to make Singleton thread like this? (Good or bad practice)

Nicolas Filotto
  • 43,537
  • 11
  • 94
  • 122
user1097772
  • 3,499
  • 15
  • 59
  • 95

2 Answers2

0

Instead of trying to reinvent the wheel, you should use a ScheduledExecutorService (which is actually a pool of threads that you can use to schedule tasks) created with Executors.newSingleThreadScheduledExecutor() (which is a pool of only one thread) to schedule your task every 300 milliseconds, then call cancel(boolean) on the corresponding Future instance when you want to stop the task.

Something like this:

// Create the scheduler that will use only one thread to execute its tasks
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
// Schedule the task every 300 milliseconds starting in 300 milliseconds
ScheduledFuture<?> future = executor.scheduleAtFixedRate(
    new Runnable() {
        @Override
        public void run() {
            if(change) labelHandle.setForeground(Color.Blue);
            else labelHandle.setForeground(Color.Black);
            change = !change; //switch the condition
        }
    }, 300L, 300L, TimeUnit.MILLISECONDS
);
...
// Stop it when it is done
future.cancel(false);

Your executor can be defined as a private static final field as you only need one scheduler such that you will then have only one thread in your entire application.

Nicolas Filotto
  • 43,537
  • 11
  • 94
  • 122
  • I know a bit about future but I'm not sure how this works. And don't believe code I don't fully understand. I have more views in application and in every view can be raised some warning message, which text can blink(according some parameter, but let says it will always blink for simplicity). The blinking is done by running new thread which change foreground color of the text. By the singleton pattern I wanted to ensure that this thread will be always only one in the application and I won't have zillion threads. – user1097772 Sep 12 '16 at 08:16
0

Here is an option to start / stop a singleton runnable

    public class Blink implements Runnable {

    private static Blink blink;
    private static Thread thread;
    private static boolean stop = false;

    @Override
    public void run() {

        while (! stop ) {

            System.out.println("running ");

            try {
                Thread.sleep(1000);
            } catch (InterruptedException ex) { ex.printStackTrace();}
        }


        System.out.println("stopped " );
    }

    public static void doBlink(boolean start) {

        if(blink == null) {

            blink= new Blink();
        }

        if(start) {

            stop = true; //stop thread if running
            thread = new Thread(blink);
            thread.start();
            stop = false;

        }else {

             stop = true;
        }

    }

    public static void main(String[] args) {

        Blink.doBlink(true);

        try {
            Thread.sleep(4000);
        } catch (InterruptedException ex) { ex.printStackTrace();}

        Blink.doBlink(false);
    }
}
c0der
  • 18,467
  • 6
  • 33
  • 65
  • Two questions: 1) if(blink == null) should be probably called with synchronized: synchronized if(blink == null) 2) thread.start(); is probalby missplaced, it should probably be used in if(blink == null) brackets after thread = new Thread(blink); because when i call doBlink(true), than doBlink(false), than doBlink(true) i will probably get IllegalThreadStateException according to this: http://stackoverflow.com/questions/1215548/is-it-legal-to-call-the-start-method-twice-on-the-same-thread – user1097772 Sep 09 '16 at 13:36