converting to ScheduledThreadPoolExecutor - java

I am still a beginner at Java so I have not learned much about threads and concurrency. However, I would like to be able to use the ScheduledThreadPoolExecutor as a timer because of the problems I am having with java.util.Timer and TimerTask. I am extremely interested in the creation of threads and know that I will be learning about them in a few weeks. However, if possible could someone give me a basic example on how to convert my current mini test program using util.timer to using a ScheduledThreadPoolExecutor?
I would like to complete this example ASAP so I don't have much time to learn about threads - no matter how much I would like to. Having said this please include anything you feel is important that a java beginner should know with regards to ScheduledThreadPoolExecutor.
Example program
I have made a quick small example to represent the problem I am having in a larger program. What this program should do is allow the user to press a button to start a counter. The user must then be able to stop and restart the counter when ever s/he wants. In the larger program it is vital that this counter remains equal so I have used the
scheduleAtFixRate()
method. It is also important that the initial delay is always the same (in this case 0).
The problem (as I am sure you will see) is that once the timer is cancelled it cannot be restarted - something that I hope the ScheduledThreadPoolExecutor will resolve.
code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.TimerTask;
import java.util.Timer;
public class Tester extends JFrame {
JButton push = new JButton("Push");
static JTextArea textOut = new JTextArea();
Timer timer = new Timer();
boolean pushed = false;
static int i = 1;
public Tester() {
super();
add(push, BorderLayout.NORTH);
add(textOut);
push.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (!pushed) {
timer.scheduleAtFixedRate(new Task(), 0, 1000);
pushed = true;
} else {
timer.cancel();
pushed = false;
}
}
});
}
static class Task extends TimerTask {
public void run() {
textOut.setText("" + i++);
}
}
public static void main(String[] args) {
Tester a = new Tester();
a.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
a.pack();
a.setVisible(true);
}
}
I use this class a lot for testing so there may be extra code (I think I removed it all).

Replace
Timer timer = new Timer();
with
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
and
class Task extends TimerTask
with
class Task implements Runnable
and
timer.scheduleAtFixedRate(new Task(), 0, 1000);
with
service.scheduleAtFixedRate(new Task(), 0, 1000, TimeUnit.MILLISECONDS);
BTW You should not be attempting to update the GUI on another thread. Instead you have to add a task to the Swing GUI Thread to perform the task
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
textOut.setText("" + i++);
}
});

Related

Timer doesn't work in java [duplicate]

I made a blackjack game, and I want the AI player to pause between taking cards. I tried simply using Thread.sleep(x), but that makes it freeze until the AI player is done taking all of his cards. I know that Swing is not thread safe, so I looked at Timers, but I could not understand how I could use one for this. Here is my current code:
while (JB.total < 21) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
System.out.println("Oh noes!");
}
switch (getJBTable(JB.total, JB.aces > 0)) {
case 0:
JB.hit();
break;
case 1:
break done;
case 2:
JB.hit();
JB.bet *= 2;
break done;
}
}
BTW, the hit(); method updates the GUI.
so I looked at Timers, but I could not understand how I could use one for this
The Timer is the solution, since as you say you are updating the GUI which should be done on the EDT.
I'm not sure what your concern is. You deal a card and start the Timer. When the Timer fires you decide to take another card or hold. When you hold your stop the Timer.
Well, the following code shows a JFrame with a JTextArea and a JButton. When the buttons is clicked, the Timer send the event repeatedly (with a second delay between them) to the actionListener related to the button which appends a line with the current time.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Calendar;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.Timer;
public class TimerTest extends JFrame implements ActionListener{
private static final long serialVersionUID = 7416567620110237028L;
JTextArea area;
Timer timer;
int count; // Counts the number of sendings done by the timer
boolean running; // Indicates if the timer is started (true) or stopped (false)
public TimerTest() {
super("Test");
setBounds(30,30,500,500);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(null);
area = new JTextArea();
area.setBounds(0, 0, 500, 400);
add(area);
JButton button = new JButton("Click Me!");
button.addActionListener(this);
button.setBounds(200, 400, 100, 40);
add(button);
// Initialization of the timer. 1 second delay and this class as ActionListener
timer = new Timer(1000, this);
timer.setRepeats(true); // Send events until someone stops it
count = 0; // in the beginning, 0 events sended by timer
running = false;
System.out.println(timer.isRepeats());
setVisible(true); // Shows the frame
}
public void actionPerformed(ActionEvent e) {
if (! running) {
timer.start();
running = true;
}
// Writing the current time and increasing the cont times
area.append(Calendar.getInstance().getTime().toString()+"\n");
count++;
if (count == 10) {
timer.stop();
count = 0;
running = false;
}
}
public static void main(String[] args) {
// Executing the frame with its Timer
new TimerTest();
}
}
Well, this code is a sample of how to use javax.swig.Timer objects. In relation with the particular case of the question. The if statement to stop the timer must change, and, obviously, the actions of the actionPerformed. The following fragment is a skeleton of the solution actionPerformed:
public void actionPerformed(ActionEvent e) {
if (e.getComponent() == myDealerComponent()) {
// I do this if statement because the actionPerformed can treat more components
if (! running) {
timer.start();
runnig = true;
}
// Hit a card if it must be hitted
switch (getJBTable(JB.total, JB.aces > 0)) {
case 0:
JB.hit();
break;
case 1:
break done;
case 2:
JB.hit();
JB.bet *= 2;
break done;
}
if (JB.total >= 21) { // In this case we don't need count the number of times, only check the JB.total 21 reached
timer.stop()
running = false;
}
}
}
IMHO this resolves the problem, now #user920769 must think where put the actionListener and the starting/stopping conditions...
#kleopatra: Thanks for show me the existence of this timer class, I don't know nothing about it and it's amazing, make possible a lot of tasked things into a swing application :)
Well, a quick explanation about Timers.
First of all, you need a java.util.Timer variable in your class and another class in your project which extends from java.util.TimerTask (let's call it Tasker).
The initialization of the Timer variable is so easy:
Timer timer = new Timer();
Now the Tasker class:
public class Tasker extends TimerTask {
#Override
public void run() {
actionToDo(); // For example take cards
}
// More functions if they are needed
}
Finally, the installation of the timer with its related Tasker:
long delay = 0L;
long period = pauseTime;
timer.schedule(new Tasker(),delay,period);
The schedule function indicates the following:
Fisrt param: Action to do each period milliseconds (Executes the run function of a TimerTask class or its extension)
Second param: When the timer must start. In this case, it starts when the schedule function is called. The following example indicates a starting 1 second after call the schedule function: timer.schedule(new Tasker(),1000,period);
Third param: milliseconds between one call of Tasker.run() function and the following call.
I hope you understand this microtutorial :). If you have any problem, ask for more detailed information!
Kind regards!
I think that in this tutorial is clear how to use Timers in order to achieve what you want, without having to deal with Threads.

Why does my java timer stop after seemingly random number of iterations?

I am trying to create a simple java program that will run indefinitely and output a number every second. I believe my code here should do this; however, it stops after the variable i gets to either 2, 3 or 4. Randomly. Most of the time it hits 3. I do not think that the program stopping is based on i at all, but something i'm overlooking perhaps.
All this program needs to do is spit out the second count using a timer. I feel like my code might be a little over complicated so please let me know if i'm making it too hard.
package testing;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class driver {
static int delay = 1000; //milliseconds
private Timer timer;
int i = 0;
public driver(){
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
System.out.println(i);
i++;
}
};
timer = new Timer(delay, taskPerformer);
timer.setInitialDelay(0);
timer.start();
}
public static void main(String args[]){
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new driver();
}
});
}
}
Everything is just right in your program, but one.
Your program starts (from main() obviously), which starts the timer, timer method initiates the process of displaying time/number every second, and after that, the main thread dies! resulting in completion of program execution.
So to avoid this you simply can keep main thread busy.
Here's the simplest way :
public static void main(String args[]){
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
driver d = new driver();
}
});
for(;;); // <-- **Check this out :D**
}

How to use Timer

I have an application made in Netbeans and I don't have any idea how to use a Timer in Java. In Winform there's a control box of Timer which is drag and use only. Now I want to use a timer for 1 seconds after about.setIcon(about4); (which is GIF) is executed.
import javax.swing.ImageIcon;
int a2 = 0, a3 = 1, a4 = 2;
ImageIcon about2 = new ImageIcon(getClass().getResource("/2What-is-the-Game.gif"));
about2.getImage().flush();
ImageIcon about3 = new ImageIcon(getClass().getResource("/3How-to-play.gif"));
about3.getImage().flush();
ImageIcon about4 = new ImageIcon(getClass().getResource("/4About-end.gif"));
about4.getImage().flush();
if(a2 == 0)
{
a2=1;
a3=1;
about.setIcon(about2);
}
else if (a3 == 1)
{
a3=0;
a4=1;
about.setIcon(about3);
}
else if (a4 == 1)
{
a4=0;
a2=0;
about.setIcon(about4);
}
}
How can I achieve this?
In Java, we have several ways of Timer implementation or rather its uses, a few of them are-
To set up a specific amount of delay until a task is executed.
To find the time difference between two specific events.
Timer class provides facility for threads to schedule tasks for future execution in a background thread. Tasks may be scheduled for one-time execution, or for repeated execution at regular intervals.
public class JavaReminder {
Timer timer;
public JavaReminder(int seconds) {
timer = new Timer(); //At this line a new Thread will be created
timer.schedule(new RemindTask(), seconds*1000); //delay in milliseconds
}
class RemindTask extends TimerTask {
#Override
public void run() {
System.out.println("ReminderTask is completed by Java timer");
timer.cancel(); //Not necessary because we call System.exit
//System.exit(0); //Stops the AWT thread (and everything else)
}
}
public static void main(String args[]) {
System.out.println("Java timer is about to start");
JavaReminder reminderBeep = new JavaReminder(5);
System.out.println("Remindertask is scheduled with Java timer.");
}
}
Read more from here:
http://javarevisited.blogspot.in/2013/02/what-is-timer-and-timertask-in-java-example-tutorial.html
http://www.javatutorialhub.com/timers-java
Declare an instance of java.util.Timer in your code (in the constructor?) and configure/control it with the methods found in the docs.
import java.util.Timer;
import java.util.TimerTask;
...
private Timer t;
public class MyClass()
{
t=new Timer(new TimerTask(){
#Override
public void run()
{
//Code to run when timer ticks.
}
},1000);//Run in 1000ms
}

Counter to Close JFrame, bring up Confirm Dialog

This post relates to my last one regarding a timer. I decided the easiest thing to do for immediate results was to just write a Counter thread that counts down from a certain time (in this case 5 seconds) and if the counter reaches 0, the JFrame closes and let's the user know that time has expired.
I'm running into some trouble, however. I cannot seem to make the JFrame close when the counter reaches 0. I'm not sure if I'm missing something stupid or if I am misunderstanding the way threads work and the way JFrames work. Here is the code, let me know what you think.
On a side note, I understand it would probably be most efficient to use a swing.Timer, but I just don't quite grasp the nature of them yet. I'm under self-imposed time constraints (I'm not a student or anything, I just like to stay motivated) and so I'm "jerry-rigging" this thing for now.
Anyway, on to the code!
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
public class RacerDoom extends JFrame {
boolean timesUp=false;
public RacerDoom() {
//create JFrame
super("Racer Doom Squared");
setSize(WIDTH,HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
if(timesUp==true) {
dispose();
JOptionPane.showConfirmDialog(null, "Time's Up! Click Okay to try again!");
}
Counter c1 = new Counter();
c1.start();
//Counter
private class Counter extends Thread {
public Counter() {}
public void run() {
for(int i=5;i>=0;i--) {
if(i==0) {
timesUp=true;
}
System.out.println(i);
try{
Thread.sleep(1000);
}
catch(InterruptedException e){}
}
}
}
...
EDIT: I have the timer implemented and working. It does exactly what I need it to, but I can't get the timer.stop(); command to work. I get the error "The local variable timer may not have been initialized.
Like I said, the timer works, it just never stops working until the program is terminated. Here is the constructor code for the JFrame, where the timer is located.
int counter = 0;
public RacerDoom() {
//create JFrame
super("Racer Doom Squared");
setSize(WIDTH,HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
final Timer timer=new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(counter>=10) {
timer.stop(); //the error occurs here
dispose();
JOptionPane.showConfirmDialog(null, "Time's Up!");
}
else{
counter++;
}
System.out.println(counter);
}
});
//inner thread
Move1 m1 = new Move1();
m1.start();
timer.start();
}
Thats easy to do with the help of a swing timer.. See this code sample:
final java.swing.Timer timer=new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(counter>5) {
timer.stop();
<dispose the fram here>
}else{
counter++;
}
}
});
timer.start();
I put this code in the constructor of my JFrame which will run in the Event despatch thread. If you dont want hang up your GUI, make sure that you run this timer on another thread and when you are disposing the JFrame wrap the call with SwingUtilities.invokeLater() - This ensures that the call gets queued on the event despatch thread.
I think your code is not working for the same reason, that you trying to something that does not get queued up in the event despatch thread. Here's an article that will get you going
http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html

Java: Flash a window to grab user's attention

Is there a better way to flash a window in Java than this:
public static void flashWindow(JFrame frame) throws InterruptedException {
int sleepTime = 50;
frame.setVisible(false);
Thread.sleep(sleepTime);
frame.setVisible(true);
Thread.sleep(sleepTime);
frame.setVisible(false);
Thread.sleep(sleepTime);
frame.setVisible(true);
Thread.sleep(sleepTime);
frame.setVisible(false);
Thread.sleep(sleepTime);
frame.setVisible(true);
}
I know that this code is scary...But it works alright. (I should implement a loop...)
There are two common ways to do this: use JNI to set urgency hints on the taskbar's window, and create a notification icon/message. I prefer the second way, since it's cross-platform and less annoying.
See documentation on the TrayIcon class, particularly the displayMessage() method.
The following links may be of interest:
New System Tray Functionality in Java SE 6
Java Programming - Iconified window blinking
TrayIcon for earlier versions of Java
Well, there are a few minor improvements we could make. ;)
I would use a Timer to make sure callers don't have to wait for the method to return. And preventing more than one flashing operation at a time on a given window would be nice too.
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import javax.swing.JFrame;
public class WindowFlasher {
private final Timer timer = new Timer();
private final Map<JFrame, TimerTask> flashing
= new ConcurrentHashMap<JFrame, TimerTask>();
public void flashWindow(final JFrame window,
final long period,
final int blinks) {
TimerTask newTask = new TimerTask() {
private int remaining = blinks * 2;
#Override
public void run() {
if (remaining-- > 0)
window.setVisible(!window.isVisible());
else {
window.setVisible(true);
cancel();
}
}
#Override
public boolean cancel() {
flashing.remove(this);
return super.cancel();
}
};
TimerTask oldTask = flashing.put(window, newTask);
// if the window is already flashing, cancel the old task
if (oldTask != null)
oldTask.cancel();
timer.schedule(newTask, 0, period);
}
}

Categories