5

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).

mKorbel
  • 109,525
  • 20
  • 134
  • 319
Saad Attieh
  • 1,396
  • 3
  • 21
  • 42
  • 2
    I feel like you're asking SO to write code for you... under a thinly veiled guise of wanting to learn threads, "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." – Alex DiCarlo Jan 14 '13 at 08:50
  • Usually a learning example does not contain wording like "it is vital that" and likewise. – SJuan76 Jan 14 '13 at 08:56
  • I hope no one is thinking that. I am passionate about programming and am studying it at university. If I had wanted to have people code my program I would have put the real code in the example rather then a Quick Test example that I made. – Saad Attieh Jan 14 '13 at 09:01
  • _I would have put the real code in the example rather then a Quick Test example that I made_ A professional would never put "real" code and would instead post a quick test example illustrating his/her problem. I have never seen a student put words such as _I would like to complete this example ASAP_ or _it is vital that_. – Guillaume Polet Jan 14 '13 at 09:06
  • Sorry and by vital I purely meant I need the program to do what I wrote. I am on my holidays which ends in a few days and when I get back to uni I will have much less time to experiment with programs like I am doing now. Instead I will be writing whatever is assigned so I use these calmer times to enhance my knowledge in Java. That is why I would like to finish the programs I am writing now ASAP before I head back. – Saad Attieh Jan 14 '13 at 09:07
  • I apologise if you don't find this believable but thanks for any support – Saad Attieh Jan 14 '13 at 09:08
  • if you are still wondering what I mean by vital it is simply that my actual program involves using a stop watch and as I mentioned, the delay should be minimal otherwise it would go out of sync with another function (not the only class in the program that is tracking time). – Saad Attieh Jan 14 '13 at 09:18

1 Answers1

23

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++);
        }
    });
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • Doing this keeps adding dead threads though. I get `pool-##-thread-1` and they never get cleaned up. Am I missing something? – kmort Dec 09 '14 at 20:31
  • @kmort I assume you are not doing a shutdown() when you are finished. – Peter Lawrey Dec 09 '14 at 20:38
  • Nope. I hadn't done that. I'm not quite sure how, as I'm kicking this off in a windowClosing() on a dialog that goes away immediately after I schedule the Runnable. Is this bad? (I'm new to Java...) – kmort Dec 09 '14 at 21:48
  • @kmort it's not bad, however you need to decide when you don't need it anymore. You can have the task call shutdown () when you don't want it to run again. – Peter Lawrey Dec 10 '14 at 02:57
  • Okay, I get it now. I simply pass a reference to the `ScheduledExecutorService service` to the Runnable, and call `service.shutdown()` when complete. Thank you Peter. Cheers. – kmort Dec 10 '14 at 14:28