I've created a timer class and am testing it with junit4. The timer is notifies another class of the time which then activates a method. While testing I am unable to check what values are sent to the observer because the compiler gets stuck in the always loop used for the timer. Here's the test and the start code for the timer.
public void testSimpleTimerAsThread() throws InterruptedException
{
SimpleTimer st = new SimpleTimer(1000);
st.start();
Thread.sleep(250); // So we are 1/4th a second different
for (int x=0;x<5;x++)
{
assertEquals(x, st.getRound()); // assumes round starts at
Thread.sleep(1000); // wait for the next time change
}
}
public void start()
{
while (flag)
{
timeChanged();
try
{
// Sleep for var seconds.
Thread.sleep(1000);
}
catch (InterruptedException e)
{
}
}
}
Thanks for the help.
In the SimpleTimer class you should be overriding the run() method, not start().
Assuming SimpleTimer extends Thread, you have overridden the method in Thread that actually creates and launches the thread, so no new thread is being created and your thread code is being executed in the main thread when you invoke start(), which is why it hangs.
Related
My code:
public class EventHandler implements Runnable, SomeEventListener {
private static final EventHandler INSTANCE = new EventHandler();
private static final Thread THREAD = new Thread(INSTANCE);
private static volatile boolean isRunning = false;
private EventHandler () {}
private static EventHandler getInstance() {
return INSTANCE;
}
public void start() {
isRunning = true;
THREAD.start();
}
public void stop() {
isRunning = false;
}
//Listener method that was overriden
public void onEvent(Event event) {
//...do stuff
}
#Override
public void run() {
//Do nothing, let the listener do its job
while (isRunning) {
try {
logger.info("Sleeping...");
Thread.sleep(5000);
logger.info("Done sleeping...");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Basically the run() method does nothing - just sleeps every 5 seconds, wakes up, sleeps again. What I don't understand is when it's asleep, this EventHandler class still gets events. How does this happen? Shouldn't the class stop receiving events since the thread is asleep?
The thread and the class are two different things. EventHandler is an object that has a dedicated thread executing its run method. At the same time it has its onEvent method which is available to get called by other threads.
Log the thread ID in the onEvent method and in the run method to confirm the sleeping thread is not involved in receiving events.
Classes don't own threads. Your THREAD is spinning doing its sleeping, logging, and flag-checking, while other threads in your program call onEvent. (Also the OS-level thread is a separate thing from the object whose reference you saved as THREAD.)
You could use a thread pool and that would keep your application alive until you shut it down. It would be better to submit Runnables to a thread pool than to give each Runnable its own dedicated thread.
That thread seems really useless. I don't know how you think Listeners work, but basically they are just references that some thread you probably never saw will use to call certain methods if they see something happen.
A listener does not just "catch" any events thrown into the room.
Like I said: This thread seems useless because it doesn't do anything. At all. The Events are called from a different thread. You don't need this one for it.
I've seen a lot of example for wait and notify, but still I have a problem.
public class Main(){
public static void main(String args[]) throws Exception {
MyThread s = new MyThread();
s.start();
}
}
class MyThread extends Thread {
public void run() {
k();
}
public synchronized void k() {
System.out.println("before wait");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("do something after wait");
}
public synchronized void m() {
for (int i=0;i<6;i++)
System.out.println(i);
notify();
}
}
The only output I get when run the program is: "before wait".
The thread you create in main invokes MyThread#k() which goes into a wait. At that point, that thread will do nothing else until it is awakened or interrupted. But the only place in your code where it could possibly be awakened is the notify in MyThread#m(). Since nothing in your program calls that method, the thread can never be awoken.
What you probably want is to add a call to s.m() right after s.start() in your main program. That way your main thread will execute the notify that's needed to wake up your thread.
Unfortunately, that's very unlikely to work. The problem is that s.start() causes your created thread to become ready to run, but it doesn't necessarily run immediately. It could well happen that your call to s.m() will complete before the created thread does anything. And then you'll still have exactly the same result as before, except that you'll see the integers 0..6 printed out before before wait. The notify will do nothing, because the child thread has not yet performed its wait. (And by the way, since both MyThread#k() and MyThread#m() are both synchronized, increasing your loop limit in MyThread#m() won't change a thing... the child thread won't be able to enter MyThread#k() while MyThread#m() is running. You could improve that by putting the notify in a sycnchronized block rather than making all of MyThread#m() synchronized.)
You can try to get around this by adding Thread.sleep(1000) before s.m() in your main program. That will almost certainly work because your main thread will yield execution, giving your JVM the opportunity to schedule the child thread for some useful work. By the time the main thread wakes out of its sleep and performs its s.m() call, the child will probably have executed its wait and you will then see your do something after wait message.
But that's still pretty crummy, because it still depends on scheduling events that you don't really have any control over. There's still no guarantee that the wait will happen before the notify.
This is why when using wait/notify you should generally arrange for there to be some sort of reliable test as to whether whatever you're waiting to be done has actually occurred. This should be a condition that, once it turns turns true, will remain true at least until the test has been subsequently performed. Then your typical wait loop looks something like this:
while (!isDone()) {
synchronized(monitorObject) {
try {
monitorObject.wait();
} catch (InterruptedException e) {
}
}
}
Putting the whole thing in a loop takes care of premature waking, e.g. due to InterruptedException.
If the required work has already occurred by the time this code is executed, no wait occurs, and the notify executed by the code that did the work was a no-op. Otherwise, this code waits, and the code completing the work will eventually do a notify which will wake this code up as required. Of course, it's critical that, at the time the notify is performed, the wait condition (isDone() above) be true and remain true at least until tested.
Here's a corrected version of your code that incorporates a proper wait loop. If you comment out the Thread.sleep() call, you will likely not see the waiting message, because the work will complete before the wait loop even starts. With the sleep included, you'll probably see the waiting message. But either way, the program will work properly.
public static void main(String[] argv) throws Exception {
MyThread s = new MyThread();
s.start();
Thread.sleep(1000);
s.m();
}
class MyThread extends Thread {
#Override
public void run() {
k();
}
private boolean done = false;
public void k() {
System.out.println("before wait");
while (!done) {
System.out.println("waiting");
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
System.out.println("do something after wait");
}
public void m() {
for (int i = 0; i < 6; i++) {
System.out.println(i);
}
synchronized (this) {
done = true;
notify();
}
}
}
The problem is, that you're not calling your m method, so notify is never called, so your thread sleeps forever. You could call it in main, after the start, using s.m():
MyThread s = new MyThread();
s.start();
s.m();
Maybe you should sleep for a little time before calling the m method, as it could run sooner than k in the thread:
s.start();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// nothing to do
}
s.m();
Not closely related to the question, but a throws declaration in main is not very advisable, even a generated printStackTrace is better than throwing the exception away.
I am writing a java swing program that involves using a thread to update the UI,
The run function in the thread contains a while loop and a sleep timer,
I want to either terminate the while loop or the thread itself when the user presses for example ctrl+c. The thread includes a sleep command, I don't want the user to have to hold down ctrl+c to terminate, I just want to be able to use those keys once.
How is this possible?
public static void main(String[] args) {
.......//Code to set up window
Thread thread = new Thread(){
#Override
public void run() {
while(user has not terminated the program with ctrl+c){
//Do Something
try{
Thread.sleep(5000);
}catch(InterruptedException e){
}
}
}
};
.......//Code to start thread
}
In Java, threads are terminated cooperatively. This means that it requires modifying both the code inside the thread as well as the code outside the thread. Outside the thread, you can signal that the thread should prepare to shutdown by using the Thread.interrupt() method. Inside the thread, you should check Thread.interrupted() to test for interruption (and break from the loop if that is the case). You should also modify your exception handler; the interrupted exception is thrown when Thread.interrupt() was called while the thread was sleeping, so you should modify the content of that handler to break from the loop.
try something like this
class A{
Thread r1Thread;
public static boolean isCtrlCPressed = false;
public static void main(String[] args) {
.......//Code to set up window
MyRun r1 = new MyRun();
r1Thread = new Thread(r1);
r1Thread.start();
}
public void someMethodThatDetectCtrlC(){
r1Thread.interrupt();
}
}
Your Thread
class MyRun implements Runnable{
#Override
public void run() {
// TODO Auto-generated method stub
try{
Thread.sleep(5000);
}catch(InterruptedException e){
}
}
}
Make a boolean called "running"
Change your while loop to while(running)
Add a keylistener, make it listen for Ctrl + C.
If it hears Ctrl + C, set running = false.
Since running == false, the while loop will then stop.
I have this piece of code:
Timeout s = new Timeout();
Timer timer = new Timer();
timer.schedule(s, 1000L); // fires after 1 second
How can I launch the following piece of code as a thread by itself? Would I need to pass the timer and Timeout to a Runnable and then start it? What happens if the thread's Run() ends before the timer is fired?
I am thinking of doing this instead:
ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
Timeout s = new Timeout(); // Timeout is a runnable
ses.schedule(s, 10, TimeUnit.SECONDS);
but how do I exit the thread after the timeout? I run out of thread after a while
Thanks
I'm not exactly sure what you're asking, but I'll give it a shot.
How can I launch the following piece of code as a thread by itself?
In short...
Timeout.java
public class Timeout extends TimerTask {
boolean isDone = false;
#Override
public void run() {
// TODO something
synchronized(this) {
isDone=true;
this.notifyAll();
}
}
public synchronized void join() throws InterruptedException {
while(!this.isDone)
this.wait();
}
}
TimeoutRunner.java
public class TimerRunner implements Runnable {
#Override
public void run() {
Timeout timeout = new Timeout();
Timer timer = new Timer();
timer.schedule(timeout, 1000L);
try {
timeout.join();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
timer.cancel();
}
}
}
Run the TimeoutRunner using:
new Thread(new TimeoutRunner()).start();
The join method will block the thread until the timeout task has completed execution. At that time you can close the Timer. This is, however, a lot of thread creation, and IMO bad programming.
When you create a Timer instance, a thread is created to execute the Timeout#run() method. The timer has it's own run method that blocks until your task is ready for execution. After the given timeout period elapses, the timer unblocks and executes your timeout.
Your TimeoutRunner thread will block until the timeout operation completes. Only then can this thread die.
The Timer class is very limited. You need to create a new instance for every task. In my option, the ScheduledExecutorService is a better option. Keep the ScheduledExecutorService open for as long as you plan on executing tasks. If you need something like a scheduled cached thread pool, feel free to use this class from one of my open-source projects (Scheduler). This works great with a cached thread pool.
Consider this class, AnimationThread:
class AnimationThread implements Runnable {
public void pause() {
doAnimation = false;
}
public void doStart(){
doAnimation = true;
}
#Override
public void run() {
// TODO Auto-generated method stub
if (doAnimation) {
//my code
}
try {
Thread.sleep(500);
}
catch (InterruptedException e) {
}
}
}
Now I am starting this thread in onCreate of an activity (just showing rough code):
AnimationThread animRunnable = new AnimationThread();
animationThread = new Thread(animRunnable);
animationThread.start();
But run() is getting called just once (I traced a log to confirm that). I just want to know that when I started the thread why run() is not getting called repeatedly with 500 sleep. It is just called once.
That is how it is supposed to be.
A Thread runs by executing its run method (just once). After that it is considered done/dead/finished/completed.
If you want to loop, you have to do it yourself (inside of the run method), or use some ExecutorService to call the Runnable repeatedly.
Of course the run() method will be executed once. If you want to repeat the statements inside the run method then you have to use loop. Take a look at TimerTask - will runs a task at a specified time or repeatedly.
EDIT:
Android - Controlling a task with Timer and TimerTask?
Timer task schedule