• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Paul Clapham
  • Ron McLeod
  • Tim Cooke
  • Junilu Lacar
Sheriffs:
  • Rob Spoor
  • Devaka Cooray
  • Jeanne Boyarsky
Saloon Keepers:
  • Jesse Silverman
  • Stephan van Hulst
  • Tim Moores
  • Carey Brown
  • Tim Holloway
Bartenders:
  • Jj Roberts
  • Al Hobbs
  • Piet Souris

Thread execution at TWO back-to-back fixed rates

 
Ranch Hand
Posts: 52
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello,

I'd like to use scheduleAtFixedRate(), or something similar, to execute some code at TWO fixed rates. ScheduleAtFixedRate won't work because it will only run with one fixed period in between each execution at some fixed (one-time) delay.

In other words, it will allow me to run some code every 5ms. I would like to run some code every 5ms, 12ms, 5ms, 12ms, 5ms, 12ms, and so on. Is there some other java library feature to do this? I'm not seeing one. Any tweak or hack to get scheduleAtFixedRate to work would be fine, also.

Thanks for your feedback!
 
Marshal
Posts: 26909
82
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Mathematically that's the same as having two threads, one which starts now and runs every 17ms and the other one which starts in 5ms and runs every 17 ms.

But in practice it isn't quite the same. The scheduleAtFixedRate() method doesn't allow two iterations of the executed task to overlap, and may start the second one late if that's going to happen. This two-threaded idea doesn't work that way out of the box, but you could possibly deal with that by having the executed task synchronize on a shared object so that two copies of it can't overlap. Yes, now we're building a second cheap hack on top of the first cheap hack...
 
Marshal
Posts: 74341
334
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
What would happen if you had two Timers running on the two threads? You cannot guarantee that the two Timers would start exactly 5″ apart, and you are sitll risking race conditions.
 
Paul Clapham
Marshal
Posts: 26909
82
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Remember I did call it a "cheap hack".
 
Simon McNamara
Ranch Hand
Posts: 52
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Alrighty, so I think I just found a stupid simple solution:



I can run this and print stuff to console in the timing I expect, but I'm pretty new to threads. Are there any peculiar timing details I'm not seeing by using sleep()? I'm sleeping the thread itself, so that shouldn't screw around with my program's other processes, right? This class will be built into a JavaFX GUI later on.

Thanks for your feedback!
 
Campbell Ritchie
Marshal
Posts: 74341
334
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Simon McNamara wrote:. . . This class will be built into a JavaFX GUI later on. . . .

That sounds hazardous. GUI frameworks are usually non‑thread‑safe, so you should run the GUI from one thread and one only. Long tasks in parallel may be run in different threads however.
 
Bartender
Posts: 4667
183
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
A disadvantage is that if you cancel right after the try has been entered, you have to wai for 7 seonds before the thread finishes, since only then do you check status.

So an alternative is something like:

and you could have
var thread = new FunctionGeneratorr2();
thread.start();
// and at any time
thread.interrupt();
To make your class a little more general, you could supply the constructor with some Runnables, and execute these inside.
But it was suggested to use two scheduleAtFixedRate()'s. What is the problem with that?
 
Simon McNamara
Ranch Hand
Posts: 52
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:

Simon McNamara wrote:. . . This class will be built into a JavaFX GUI later on. . . .

That sounds hazardous. GUI frameworks are usually non‑thread‑safe, so you should run the GUI from one thread and one only. Long tasks in parallel may be run in different threads however.



I mean only that a user can create a FunctionGenerator object as a program feature. The two threads are otherwise completely separate. Am I misunderstanding the potential risk here?

A disadvantage is that if you cancel right after the try has been entered, you have to wai for 7 seonds before the thread finishes, since only then do you check status.



I'm not so concerned with that, since I the typical use case for this code will be states that persist for tens of milliseconds, rather than around 7 seconds. I just used full seconds for illustration.

...it was suggested to use two scheduleAtFixedRate()'s. What is the problem with that?



It's not clear to me how I would write this and keep the two synchronized, e.g., one starts at the end of the first and so on. I do like the scheduleAtFixedRate() methods since the timing won't "drift" over time due to subtle delays in execution inside of run(). I'm just not seeing how to do this well.

Many thanks for the feedback.
 
Campbell Ritchie
Marshal
Posts: 74341
334
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
If the two threads really run separately, then I think you are right: there won't be any problems.
Can you write a timer firing every second and count 5 or 17 actions?
 
Piet Souris
Bartender
Posts: 4667
183
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I just tried:

And it seems to work just fine.

But your Thread should also work. Well, I'm curious to see what you have in mind, so please show us when you have some working code!
 
Simon McNamara
Ranch Hand
Posts: 52
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hey All!

Well, turns out that the timing (to hardware) for this code is abysmal. As a result, I have abandoned this thread structure. Many thanks for your feedback.

Until next time,
 
Simon McNamara
Ranch Hand
Posts: 52
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello all,

I am reviving this thread since I have now encountered a need which, ironically, more closely matches the title of this thread than my original description.

In this new version of reality, I'd like to use ScheduledThreadPoolExecutor#scheduleAtFixedRate to run some simple initial code once. Then, while the period of that first schedule is waiting, use a second ScheduledThreadPoolExecutor to execute another piece of code at regular intervals. When the first period completes and restarts, that second ScheduledThreadPoolExecutor stops temporarily.

I wrote this up to test this function:



The outer schedule succeeds at running a thing once. But, the inner timer never cancels. Therefore, the inner timer runs 5 times on the first outer period, then 10, then 15, then 20, and so on.

Any suggestions are much appreciated.

Thanks,
 
Paul Clapham
Marshal
Posts: 26909
82
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I would avoid cancelling a TimerTask and then trying to reuse it. Likewise I would avoid terminating a ScheduledThreadPoolExecutor and then trying to reuse it. I would suggest creating new TimerTask and ScheduledThreadPoolExecutor objects instead.

Although, after reading the comments in your code it's pretty clear that I don't understand what you were trying to do. It seems like you think that cancelling the TimerTask will automatically terminate the ScheduledThreadPoolExecutor which it ran. Or maybe you thought that it was possible to pause a ScheduledThreadPoolExecutor and then allow it to continue, but I don't see any support for that idea in the documentation.

But be that as it may, the end product of all of that is that I don't understand your requirements. If you want to "run simple initial code once" then I don't understand why you need to execute that in a thread pool. And I don't understand what it means for the task in that thread pool to "wait" or to "complete and restart". I believe it would help if you described your requirements instead of your chosen implementation.
 
Simon McNamara
Ranch Hand
Posts: 52
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

It seems like you think that cancelling the TimerTask will automatically terminate the ScheduledThreadPoolExecutor which it ran. Or maybe you thought that it was possible to pause a ScheduledThreadPoolExecutor and then allow it to continue



Yes, this is what I thought. Pausing the second timer would also do fine, but I was unable to achieve this behavior. Perhaps I'm attempting a bad idea.

My requirements are the following: I'd like one process to occur every X period. This is the initial attraction to ScheduledThreadPoolExecutor#ScheduledAtFixedRate. Within that X period, after some simple initial code runs, I must sequence execution of a subroutine at regular intervals so I can acquire and average some data temporally (need not be perfectly precise, since I'll be averaging hundreds of samples within the X period). All of this is done with Threads because this code will be later migrated to a GUI. There will be no shared memory between threads, so I'm not concerned about data races.

Last night I continued working on this problem and I came up with the following:



This code works, but it seems inelegant to spawn and throw away threads like this. But maybe that's normal work flow. Not sure.

I recognize also that the while-loop in PulseThread is providing a sort of blocking, but my guess is that nothing stops another thread from the operating system from interrupting execution of PulseThread, throwing off the temporal interval. I recognize also that the threads in main can start in any order, but that doesn't matter for my application.

In my ignorance, I'm attempting to transition from the "I got a thing to work" stage of my skills and into the robust code-writing part of my skills. Threads are my weak spot at the moment. Any feedback is welcomed.

Thank you,
 
Saloon Keeper
Posts: 13366
295
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Don't call classes that implement Runnable "WhateverThread". They are not threads. They are tasks. The fact that Sun decided to make the Thread class implement Runnable was a huge mistake that confuses many generations of Java programmers to make similar mistakes with their own code.

If you rename your PulseThread class to PulseTask, it might become more clear that it is not doing what you think it does. Calling PulseTask.run() from SweepThread (or rather, SweepTask) does nothing but execute the body of the run() method in the same thread that is currently executing SweepThread.run(). No concurrency actually takes place.

Even though you didn't spawn any threads in the code you wrote, NEVER start doing it in the future. In fact, I would almost go so far as to say NEVER refer to the Thread class to begin with. The only methods that have a legitimate use in business logic (not debugging) are interrupted() and isInterrupted(). All other methods are either dangerous, unreliable, or superseded by other concurrency classes.

If you already know that your tasks are going to be run in the background in a JavaFX GUI, then you may already want to let them implement javafx.concurrent.Task instead of Runnable. Let a ScheduledExecutorService execute your tasks, and instead of calling Thread.sleep() to wait before doing more work, just schedule a new task to perform the remaining work after the specified waiting period.
 
Paul Clapham
Marshal
Posts: 26909
82
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Simon McNamara wrote:This code works, but it seems inelegant to spawn and throw away threads like this.



Absolutely not. It's totally normal to create objects whenever you need them in Java. Don't try to reuse objects in order to save something, just create new ones. And a Thread is an object just like any other type of object.

Yes, I know there are systems which use Thread pools so that they don't have to keep creating Threads, because apparently there's overhead in creating a Thread. This could be important in systems which generate a lot of Threads.

But that's an optimization, so you shouldn't attempt it prematurely. And anyway your ExecutorService is using a thread pool. So instead of trying to pause an ExecutorService, just terminate it and start a new ExecutorService after pausing for the requisite time.
 
reply
    Bookmark Topic Watch Topic
  • New Topic