Accessing global class variable modified inside TimerTask() - java

How do I access class variable that is modified inside a TimerTask(). Here's an example:
public class Foo{
// Global variables
private int count = 0;
private Timer fooTimer;
public void startTimerTask(){
TimerTask fooTimerTask = new TimerTask(){
int c = 0;
public void run(){
c = count; // Using count here and updating its value
c++; // Local counter is incremented here
count = c; // Reassigning count
System.out.println(count); // Prints updated value
}
}
fooTimer.schedueleAtFixedRate(fooTimerTask, 0, 2000);
}
public static void main(String args[]){
// Start new timer and start tasks
fooTimer = new Timer();
startTimerTask();
// Trying to check value of count outside TimerTask()
count = count + 5;
System.out.println("Count: "+count) // Count returns 5
}
}
Using the above example, I would like to figure out how I can access modified value of count from TimerTask() and modify it in main() so that it also reflects on count used in TimerTask().
I understand that Java creates a copy of the original count and passes that copy to the TimerTask (which is an anonymous inner class) to be used upon.
But is there a way to use count as a shared resource?
I have also tried using single-element int array instead of int variable as count. But it still shows the same result.

This topic has been addressed many times on Stack Overflow, apparently a common schoolwork assignment. So I'll be brief. Search Stack Overflow to learn more.
AtomicInteger
But is there a way to use count as a shared resource?
Yes. Make the shared count an AtomicInteger.
Also, the Timer/TimerTask classes were supplanted many years ago by the Executors framework added to Java 5, as noted in their Javadoc.
By the way, watch your naming. Class names start with uppercase letter in Java, by convention.
By the way, your // Global variables label is a misnomer. What you are labeling are commonly called "member fields" or "instance variables". Closer to a true “global variable” in Java would be a static variable.
package work.basil.demo;
import java.util.concurrent.atomic.AtomicInteger;
public class Foo{
// Member field variables
public AtomicInteger counter = new AtomicInteger( 0 ) ;
}
Do your tasks in background threads.
You can define your Runnable/Callable using either lambda syntax or conventional syntax.
Obtain a scheduled executor service from Executors.
Notice that the main thread accesses the counter to obtain its current value while the background thread may be modifying that value. The AtomicInteger class makes thread-safe our threaded calls to get and updateAndGet.
package work.basil.demo;
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.*;
import java.util.function.IntUnaryOperator;
public class FooApp
{
public static void main ( String[] args )
{
System.out.println( "Our demo's `main` method is starting. " + Instant.now() );
Foo foo = new Foo();
IntUnaryOperator unaryOperator = ( int x ) -> ( x + 5 );
Runnable task = ( ) -> {
int newCount = foo.counter.updateAndGet( unaryOperator );
System.out.println( "New count is " + newCount + " at approximately " + Instant.now() ); // Beware: These calls may *not* appear on console in expected sequence.
};
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
ScheduledFuture < ? > sf = ses.scheduleAtFixedRate( task , 0 , 2 , TimeUnit.SECONDS );
// Let our background task run a few times.
// Check the current value once in a while.
for ( int i = 0 ; i < 3 ; i++ )
{
try { Thread.sleep( Duration.ofSeconds( 5 ).toMillis() ); } catch ( InterruptedException e ) { e.printStackTrace(); }
System.out.println( "Main thread reports counter is " + foo.counter.get() + " at " + Instant.now() );
}
try { Thread.sleep( Duration.ofSeconds( 20 ).toMillis() ); } catch ( InterruptedException e ) { e.printStackTrace(); }
ses.shutdown();
try { ses.awaitTermination( 1 , TimeUnit.MINUTES ); } catch ( InterruptedException e ) { e.printStackTrace(); }
System.out.println( "Our demo's `main` method is ending. " + Instant.now() );
}
}
When run.
Our demo's `main` method is starting. 2021-06-17T22:02:47.679682Z
New count is 5 at approximately 2021-06-17T22:02:47.692962Z
New count is 10 at approximately 2021-06-17T22:02:49.696992Z
New count is 15 at approximately 2021-06-17T22:02:51.696261Z
Main thread reports counter is 15 at 2021-06-17T22:02:52.697280Z
New count is 20 at approximately 2021-06-17T22:02:53.696181Z
New count is 25 at approximately 2021-06-17T22:02:55.696448Z
New count is 30 at approximately 2021-06-17T22:02:57.696376Z
Main thread reports counter is 30 at 2021-06-17T22:02:57.702464Z
New count is 35 at approximately 2021-06-17T22:02:59.696243Z
New count is 40 at approximately 2021-06-17T22:03:01.696155Z
Main thread reports counter is 40 at 2021-06-17T22:03:02.707548Z
New count is 45 at approximately 2021-06-17T22:03:03.696134Z
New count is 50 at approximately 2021-06-17T22:03:05.696130Z
New count is 55 at approximately 2021-06-17T22:03:07.695878Z
New count is 60 at approximately 2021-06-17T22:03:09.695790Z
New count is 65 at approximately 2021-06-17T22:03:11.696289Z
New count is 70 at approximately 2021-06-17T22:03:13.696278Z
New count is 75 at approximately 2021-06-17T22:03:15.696278Z
New count is 80 at approximately 2021-06-17T22:03:17.696187Z
New count is 85 at approximately 2021-06-17T22:03:19.696101Z
New count is 90 at approximately 2021-06-17T22:03:21.696009Z
Our demo's `main` method is ending. 2021-06-17T22:03:22.712192Z

Related

How to check performace of Multi Threading over using only a single thread?

I'm studying Java multi threading and trying to check performance with multiple threads.I am trying to check whether multi threading is better than with single thread.
So, I wrote a code which sums to limit.
It is working as I expected(multiple threads are faster than single thread) when limit gets larger but it didn't when limit is small like 100000L.
Is this due to context-switching ? and is the code below is appropriate to check performance of multi threading ?
public class MultiThreadingSum {
long count = 0;
static long limit = 1000000000L;
static void compareMultipleThreadToSingleThread(int threadCnt) {
Runnable r = () -> {
MultiThreadingSum mts = new MultiThreadingSum();
long startTime = System.nanoTime();
while(++mts.count<=limit);
long endTime = System.nanoTime();
long estimatedTime = endTime - startTime;
double seconds = estimatedTime / 1000000000.0;
System.out.println(Thread.currentThread().getName()+", elapsed time : "+seconds);
};
for(int i=0; i<threadCnt; i++) {
new Thread(r, "multiThread"+i).start();
}
Runnable r2 = () -> {
MultiThreadingSum mts = new MultiThreadingSum();
long startTime = System.nanoTime();
while(++mts.count<=limit*threadCnt);
long endTime = System.nanoTime();
long estimatedTime = endTime - startTime;
double seconds = estimatedTime / 1000000000.0;
System.out.println(Thread.currentThread().getName()+", elapsed time : "+seconds);
};
new Thread(r2, "singleThread").start();
}
public static void main(String[] args) {
compareMultipleThreadToSingleThread(3);
}
}
Your code does not wait for the 3-thread experiment to finish before running the single-thread experiment. So you may be contaminating your results.
Your code seems needlessly complicated. Can't we run two separate experiments, one with 3 threads and one with 1 thread, separately, to reuse code?
In modern Java, we rarely need to address the Thread class. Instead, use the executor service framework added to Java 5.
Putting this all together, perhaps your experiment should look more like the following.
Caveat: This is just a very rough cut, I've not thought it through, and my caffeination has been exhausted. So revise this code thoughtfully. Perhaps I can revise this code in a day or two.
package work.basil.threading;
import java.time.Duration;
import java.time.Instant;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class Loopy
{
public static void main ( String[] args )
{
Loopy app = new Loopy();
List < Integer > inputThreadsLimit = List.of( 1 , 3 , ( Runtime.getRuntime().availableProcessors() - 1 ) );
for ( Integer numberOfThreads : inputThreadsLimit )
{
System.out.println("----------| Experiment for thread count: " + numberOfThreads + " |--------------------------");
Duration duration = app.demo( numberOfThreads ); // Waits here for the experiment to run to completion.
System.out.println( numberOfThreads + " = " + duration + " total, each: " + duration.dividedBy( numberOfThreads ) );
}
}
// Member fields
final private AtomicInteger count = new AtomicInteger( 0 );
private Duration demo ( final int numberOfThreads )
{
ExecutorService executorService = Executors.newFixedThreadPool( numberOfThreads );
long start = System.nanoTime();
for ( int i = 0 ; i < numberOfThreads ; i++ )
{
executorService.submit( new Task() );
}
executorService.shutdown(); // Ask the executor service to shutdown its backing pool of threads after all submitted tasks are done/canceled/failed.
try { executorService.awaitTermination( 1 , TimeUnit.HOURS ); } catch ( InterruptedException e ) { e.printStackTrace(); } // Tries to force the shutdown after timeout.
Duration elapsed = Duration.ofNanos( System.nanoTime() - start );
return elapsed;
}
class Task implements Runnable
{
#Override
public void run ( )
{
int countSoFar = count.incrementAndGet(); // Thread-safe way to access, increment, and write a counter.
// … add code here to do some kind of work …
System.out.println( "Thread ID " + Thread.currentThread().getId() + " is finishing run after incrementing the countSoFar to: " + countSoFar + " at " + Instant.now() );
}
}
}
this is not a good example. the multi and single threaded solutions run simultaneously and on the same counter. so practically you run one multi threaded process with four threads. you need to run one solution until thread is complete and shutdown, then the other. the easiest solution would be to run the single threaded process as a simple loop in the main method and run the multi threaded solution after the loop completes. also, i would have two separate counters, or, you can assign zero to counter after single thread loop completes

Java Multi-threading : Unexpected result

I am working on a Enterprise application. I am facing some issues while running application in multithreaded environment. I am writing a program in which there is a variable whose value is getting updated(incremented) at very fast rate (for example 10000 updates/persecond). A loop runs for certain iterations and the value of the variable is incremented and stored in HashMap. Once the loop terminates and value the variable in HashMap is printed. I am getting unexpected value of the variable.
Here is demo program (Please read comments for better understanding) :
class test implements Runnable {
static ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
static AtomicInteger value_to_be_incremented_stored = new AtomicInteger(0); // variable whose value to be updated
static AtomicInteger i = new AtomicInteger(0); // this runs the loop
#Override
public void run() {
for (i.set(0); i.get() < 100000; i.incrementAndGet()) {
/*
This loop should run 100000 times and when loop terminates according to me value of variable
"value_to_be_incremented_stored" should be 100000 as its value is incremented
100000 times the loop also runs 100000 times.
*/
System.out.println("Thread > " + Thread.currentThread() + " " + value_to_be_incremented_stored.incrementAndGet());
map.put("TC", value_to_be_incremented_stored.intValue());
}
System.out.println("Output by Thread " + Thread.currentThread() + " " + map.toString());
}
public static void main(String[] args) {
test t1 = new test();
Thread thread1 = new Thread(t1);
thread1.setName("Thread 1");
Thread thread2 = new Thread(t1);
thread2.setName("Thread 2");
Thread thread3 = new Thread(t1);
thread3.setName("Thread 3");
Thread thread4 = new Thread(t1);
thread4.setName("Thread 4");
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
}
Output (it varies) :
Issue :
I am running loop for 100000 times (i.get() < 100000) then how come value of variable value_to_be_incremented_stored becomes more than 100000.
I found three defects. One there is a race condition in the for loop between the point where you compare the loop counter, and where you increment it. You should do this in one step to get an atomic operation:
for ( ; i.incrementAndGet() < 100000; ) {
The other is there is also a race condition between the increment of your counter, and placing it in the map. Even though you increment these in series, any thread could be have a different value internally (it's at a different point in the loop) and it could put a previous value in the global map. You need atomicity here to to make sure the value you increment is the value you place in the loop.
synchronized( lock ) {
value_to_be_incremented_stored.incrementAndGet();
map.put("TC", value_to_be_incremented_stored.intValue());
}
Finally for some reason the < comparison produces a value of 99999 for me. I had to use <= to fix it.
(And as we discussed in the comments, setting i.set(0) at the start of each for loop doesn't work for fairly obvious reasons. Four defects, I guess.)
class ThreadTestX implements Runnable {
static ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
static AtomicInteger value_to_be_incremented_stored = new AtomicInteger(0); // variable whose value to be updated
static AtomicInteger i = new AtomicInteger(0); // this runs the loop
static final Object lock = new Object();
#Override
public void run() {
for ( ; i.incrementAndGet() <= 100000; ) {
/*
This loop should run 100000 times and when loop terminates according to me value of variable
"value_to_be_incremented_stored" should be 100000 as its value is incremented
100000 times the loop also runs 100000 times.
*/
synchronized( lock ) {
value_to_be_incremented_stored.incrementAndGet();
// System.out.println("Thread > " + Thread.currentThread() +
// " " + value_to_be_incremented_stored.get());
map.put("TC", value_to_be_incremented_stored.intValue());
}
}
System.out.println("Output by Thread " + Thread.currentThread()
+ " " + map.toString());
}
public static void main(String[] args) {
ThreadTestX t1 = new ThreadTestX();
Thread thread1 = new Thread(t1);
thread1.setName("Thread 1");
Thread thread2 = new Thread(t1);
thread2.setName("Thread 2");
Thread thread3 = new Thread(t1);
thread3.setName("Thread 3");
Thread thread4 = new Thread(t1);
thread4.setName("Thread 4");
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
}
Output:
run:
Output by Thread Thread[Thread 4,5,main] {TC=100000}
Output by Thread Thread[Thread 3,5,main] {TC=100000}
Output by Thread Thread[Thread 1,5,main] {TC=100000}
Output by Thread Thread[Thread 2,5,main] {TC=100000}
BUILD SUCCESSFUL (total time: 0 seconds)
Afterthoughts: And in spite of getting marked correct, I'm not sure I was correct. The problem here is that you are trying to keep three things in sync: the loop counter i, the value to be incremented, and the map. Allowing any of these to be executed outside of a synchronized block may invite them to be in an unexpected state. I think the following may be safer:
#Override
public void run() {
for ( ;; ) {
synchronized( lock ) {
if( i.incrementAndGet() <= 100000 ) {
value_to_be_incremented_stored.incrementAndGet();
map.put("TC", value_to_be_incremented_stored.intValue());
}
else
break;
}
}
System.out.println("Output by Thread " + Thread.currentThread()
+ " " + map.toString());
}
This removes the need for declaring the variables as AtomicInteger, but I don't see how else you ensure that their values don't change (due to some other thread) as that loop executes.
Your "demo program" suffers from two simultaneous defects.
Defect #1 is the i.set( 0 ) pointed out by tsolakp. You say you fixed that but you are still getting a value of more than 100000. I also tried it and indeed, the final value is still larger than 100000.
I modified the program to be able to create an arbitrary number of threads, and I tried with 3, 10, and 20 threads. I got a final number of 100003, 100009, and 100019 respectively. See a pattern? So:
Defect #2 is that on the last iteration, when the value of i is 99999, the expression i.get() < 100000 is true for all threads, so all threads proceed to execute once more. The i.incrementAndGet() clause is visually sitting right next to i.get() < 1000000; but it does not get executed until the end of the loop.
So, all threads get a chance to increment i once more after the last iteration.
Everytime a new thread enters the run method it will reset your i count to zero via the first statement in the for loop by calling i.set(0).
Update: Next step after fixing reset issue, is to step through the code and see how the threads will behave.
Lets say three threads get inside the for loop while the fourth thread increments i. What will happen is that value_to_be_incremented_stored will increment 3 times and i only one time.

Synchronisation object to ensure all tasks are completed

Which Java synchronisation object should I use to ensure an arbitrarily large number of tasks are completed? The constraints are that:
Each task takes a non-trivial amount of time to complete and it is appropriate to perform tasks in parallel.
There are too many tasks to fit into memory (i.e. I cannot put a Future for every task into a Collection and then call get on all the futures).
I do not know how many tasks there will be (i.e. I cannot use a CountDownLatch).
The ExecutorService may be shared so I cannot use awaitTermination( long, TimeUnit )
For example, with Grand Central Dispatch, I might do something like this:
let workQueue = dispatch_get_global_queue( QOS_CLASS_BACKGROUND, 0 )
let latch = dispatch_group_create()
let startTime = NSDate()
var itemsProcessed = 0
let countUpdateQueue = dispatch_queue_create( "countUpdateQueue", DISPATCH_QUEUE_SERIAL )
for item in fetchItems() // generator returns too many items to store in memory
{
dispatch_group_enter( latch )
dispatch_async( workQueue )
{
self.processItem( item ) // method takes a non-trivial amount of time to run
dispatch_async( countUpdateQueue )
{
itemsProcessed++
}
dispatch_group_leave( latch )
}
}
dispatch_group_wait( latch, DISPATCH_TIME_FOREVER )
let endTime = NSDate()
let totalTime = endTime.timeIntervalSinceDate( startTime )
print( "Processed \(itemsProcessed) items in \(totalTime) seconds." )
It produces output that looks like this (for 128 items): Processed 128 items in 1.846794962883 seconds.
I tried something similar with a Phaser:
final Executor executor = new ThreadPoolExecutor( 64, 64, 1l, MINUTES, new LinkedBlockingQueue<Runnable>( 8 ), new CallerRunsPolicy() );
final Phaser latch = new Phaser( 0 );
final long startTime = currentTimeMillis();
final AtomicInteger itemsProcessed = new AtomicInteger( 0 );
for( final String item : fetchItems() ) // iterator returns too many items to store in memory
{
latch.register();
final Runnable task = new Runnable() {
public void run() {
processItem( item ); // method takes a non-trivial amount of time to run
itemsProcessed.incrementAndGet();
latch.arrive();
}
};
executor.execute( task );
}
latch.awaitAdvance( 0 );
final long endTime = currentTimeMillis();
out.println( "Processed " + itemsProcessed.get() + " items in " + ( endTime - startTime ) / 1000.0 + " seconds." );
The tasks do not always complete before the last print statement and I might get output that looks like this (for 128 items): Processed 121 items in 5.296 seconds. Is the Phaser even the right object to use? The documentation indicates it only supports 65,535 parties so I would need to either batch the items to be processed or introduce some sort of Phaser tiering.
The problem with the Phaser usage in this example is that the CallerRunsPolicy allows a task to execute on the initiating thread. Thus, while the loop is still in progress, the number of arrived parties can equal the number of registered parties, causing the phase to increment. The solution is to initialise the Phaser with 1 party then, when the loop is finished, arrive and wait for the other parties to arrive. This ensures the phase does not increment to 1 until all the tasks are complete.
final Executor executor = new ThreadPoolExecutor( 64, 64, 1l, MINUTES, new LinkedBlockingQueue<Runnable>( 8 ), new CallerRunsPolicy() );
final Phaser latch = new Phaser( 1 );
final long startTime = currentTimeMillis();
final AtomicInteger itemsProcessed = new AtomicInteger( 0 );
for( final String item : fetchItems() ) // iterator returns too many items to store in memory
{
latch.register();
final Runnable task = new Runnable() {
public void run() {
processItem( item ); // method takes a non-trivial amount of time to run
itemsProcessed.incrementAndGet();
final int arrivalPhase = latch.arrive();
}
};
executor.execute( task );
}
latch.arriveAndAwaitAdvance();
final long endTime = currentTimeMillis();
out.println( "Processed " + itemsProcessed.get() + " items in " + ( endTime - startTime ) / 1000.0 + " seconds." );
"to ensure an arbitrarily large number of tasks are completed" - the simplest way is to maintain a counter of completed tasks, with blocking operation to wait that given number of task is reached. There is no such ready class, but it is easy to make one:
class EventCounter {
long counter=0;
synchronized void up () {
counter++;
notifyAll();
}
synchronized void ensure (long count) {
while (counter<count) wait();
}
}
"There are too many tasks to fit into memory" - so the process of submitting new tasks must be suspended when the number of running tasks is too high. The simplest way is to consider the number of running tasks as a resource and count it with a semaphore:
Semaphore runningTasksSema=new Semaphore(maxNumberOfRunningTasks);
EventCounter eventCounter =new EventCounter ();
for( final String item : fetchItems() ) {
final Runnable task = new Runnable() {
public void run() {
processItem( item );
runningTasksSema.release();
eventCounter.up();
}
};
runningTasksSema.aquire();
executor.execute(task);
}
When a thread wants to ensure some given number of tasks are completed, it invokes:
eventCounter.ensure(givenNumberOfFinishedTasks);
Asynchronous (nonblocking) versions of runningTasksSema.aquire() and eventCounter.ensure() operations can be designed, but they would be more complex.
In case if you're on java8 you can use CompletableFuture
java.util.concurrent.CompletableFuture.allOf(CompletableFuture<?>... cfs)
that will wait for results of all futures in passed array.

Use threading in a loop, how to finish for loop before reaching to end of the main program?

My expected output is
Count : 1
Count : 2
Count : 3
Count : 4
Count : 5
I have tried synchronized and Lock but neither of them works. I reach to
Ending Main
sooner than I finish the loop completely. Current output is:
Starting Main
Count : 1
Count : 2
Count : 3
Count : 4
Ending Main
Count : 5
Any Idea why Count : 5 is after Ending Main? Here is my code:
public class Demo {
public static void main( String [] args ) {
System.out.println( "Starting Main" ) ;
for ( int i = 1 ; i <= 5 ; i++ ) {
Thread numberThread = new Thread(new NumberTask(i)) ;
numberThread.start() ;
}
System.out.println( "Ending Main" ) ;
}
}
class NumberTask implements Runnable {
private Lock bankLock = new ReentrantLock();
int count ;
public NumberTask( int count ) {
this.count = count ;
}
synchronized public void run() {
bankLock.lock();
try {
System.out.println( "Count : " + count ) ;
} finally {
bankLock.unlock();
}
}
}
Any Idea why "Count : 5" is after "Ending Main"?
When a thread is started, there is no guarantee that it starts running immediately. It is normal for the thread that forked the new thread to continue to run as the new thread initializes. So, after the main thread starts the 5th thread, it continues to run and beats the thread to the System.out.println("Ending Main"); statement.
It is important to realize that the whole point of threads is that they run in an asynchronous manner. Because the threads can be scheduled on separate CPUs/cores running concurrently, it is often very hard to predict the order of operations in a thread program. For example. it is also possible that you might see "Count 2" printed before "Count 1" just because of thread race conditions. I just ran it starting 500 threads and I saw:
Count : 128
Count : 130
Count : 129
Count : 131
Also, because your bankLock is local to your NumberTask class, it will not lock between threads. You could make the lock static to NumberTask to have there be one lock per-class or you could instantiate the lock in main and pass it into the NumberTask constructor. You really don't need the lock here since the System.out is a PrintStram which is a synchronized object. The same goes for the synchronized run() method. Since you will be synchronizing on the NumberTask instance, it doesn't do anything because no other thread will be synchronizing on the same object.
You can use join() to wait for other thread to finish. Your code need to be updated as follows:
public static void main( String [] args ) {
System.out.println( "Starting Main" ) ;
Thread numberThread;
for ( int i = 1 ; i <= 5 ; i++ ) {
numberThread = new Thread(new NumberTask(i)) ;
numberThread.start() ;
}
numberThread.join();
System.out.println( "Ending Main" ) ;
}
Execution of threads is not predictable, so you get this behavior. Use join() method to make one thread's execution to the end of another thread's execution.
Kindly read Java thread unpredictable

How to generate random numbers at set time intervals?

I have developed code in Java for generating ten random numbers from a range 0 to 99. The problem is I need to generate a random number for every 2 min. I am new to this area and need your views.
This example adds a random number to a blocking dequeue every two minutes. You can take the numbers from the queue when you need them. You can use java.util.Timer as a lightweight facility to schedule the number generation or you can use java.util.concurrent.ScheduledExecutorService for a more versatile solution if you need more sophistication in the future. By writing the numbers to a dequeue, you have a unified interface of retrieving numbers from both facilities.
First, we set up the blocking queue:
final BlockingDequeue<Integer> queue = new LinkedBlockingDequeue<Integer>();
Here is the setup with java.utilTimer:
TimerTask task = new TimerTask() {
public void run() {
queue.put(Math.round(Math.random() * 99));
// or use whatever method you chose to generate the number...
}
};
Timer timer = new Timer(true)Timer();
timer.schedule(task, 0, 120000);
This is the setup with java.util.concurrent.ScheduledExecutorService
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
Runnable task = new Runnable() {
public void run() {
queue.put(Math.round(Math.random() * 99));
// or use whatever method you chose to generate the number...
}
};
scheduler.scheduleAtFixedRate(task, 0, 120, SECONDS);
Now, you can get a new random number from the queue every two minutes. The queue will block until a new number becomes available...
int numbers = 100;
for (int i = 0; i < numbers; i++) {
Inetger rand = queue.remove();
System.out.println("new random number: " + rand);
}
Once you are done, you can terminate the scheduler. If you used the Timer, just do
timer.cancel();
If you used ScheduledExecutorService you can do
scheduler.shutdown();
You have two requirements which are unrelated:
Generate random numbers
Perform the task every 2 minutes.
To do anything every 2 minutes you can use a ScheduledExecutorService.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.Timer;
public class TimerExample {
Random rand = new Random();
static int currRand;
TimerExample() {
currRand = rand.nextInt(99);
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
currRand = rand.nextInt(99);
}
};
Timer timer = new Timer(2000, actionListener);
timer.start();
}
public static void main(String args[]) throws InterruptedException {
TimerExample te = new TimerExample();
while( true ) {
Thread.currentThread().sleep(500);
System.out.println("current value:" + currRand );
}
}
}
EDIT: Of course you should set 2000 in new Timer(2000, actionListener); to 120 000 for two minutes.
You can schedule your program to be run once every two minutes using whatever scheduling features are available to you in your target environment (e.g., cron, at, Windows Scheduled Tasks, etc.).
Or you can use the Thread#sleep method to suspend your application for 2,000ms and run your code in a loop:
while (loopCondition) {
/* ...generate random number... */
// Suspend execution for 2 minutes
Thread.currentThread().sleep(1000 * 60 * 2);
}
(That's just example code, you'll need to handle the InterruptedException and such.)
I'm not entirely sure I understand the problem. If you wish to generate a different random number every two minutes, simply call your rnd function every two minutes.
This could be as simple as something like (pseudo-code):
n = rnd()
repeat until finished:
use n for something
sleep for two minutes
n = rnd()
If you want to keep using the same random number for two minutes and generate a new one:
time t = 0
int n = 0
def sort_of_rnd():
if now() - t > two minutes:
n = rnd()
t = now()
return n
which will continue to return the same number for a two minute period.

Categories

Resources