I have a main form with a button, that when pressed, should start a new count-down timer thread.
This is the code in the button's action listener:
Counter c = new Counter(timeToFinish);
This is the code for the Counter class:
class Counter implements Runnable {
int waitingTime = 0;
Thread myCounter = new Thread(this);
public Counter(int waitingTime)
{
this.waitingTime = waitingTime;
myCounter.run();
}
public void run(){
//Start countdown:
do
{
waitingTime -= 1;
try {
Thread.sleep(1000);
System.out.println(waitingTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (waitingTime >= 0);
}
}
The problem is, when I create a new instance of the Counter class, it pauses the whole program, not just that thread! The problem must be with "Thread.sleep".
Because you are directly calling the run method.
Instead you should wrap it in a Thread and start the thread.
For e.g., replace
myCounter.run();
by
new Thread(this).start();
Just because you call the run method from the Counter constructor. That's not how it works with threads. You'll have to remove this call, wrap the Runnable in a Thread instance and call start() on the thread:
new Thread(new Counter(2)).start();
You aren't actually start()ing multiple threads.
The Thread.run() method simply runs the code associated with the thread, like any other normal function. It doesn't start a separate thread.
You need to call Thread.start(), to start a new thread and run your code in it.
You should use start() method of your thread. Use
c.start();
otherwise you have a class and you are invoking one of its methods, and of course it is running in main thread and sleeping the main thread.
You're calling run directly, it'll run in the current thread, and sleep the current thread, which I guess is the event thread. This cause the pause in your program.
You should use SwingUtilities class
see
http://www.java2s.com/Code/Java/Threads/InvokeExampleSwingandthread.htm
// Report the result using invokeLater().
SwingUtilities.invokeLater(new Runnable() {
public void run() {
resultLabel.setText("Ready");
setEnabled(true);
}
});
}
};
Related
I am dealing with threads and I want to run this code whenever I open Cal_JInternalFrame. It runs the fist time, but whenever I reopen the frame, it doesn't run again. I use t1.interrupted() at exit time of the whole application. The code is:
Thread t1 = new Thread( new Runnable() {
#Override
public void run() {
while ( !t1.isInterrupted() ) {
// ......... Oil Calculation Thread ...
int price = (Integer.parseInt(jLabel22.getText()));
int qty = (Integer)jSpinner8.getValue();
int totalOil =qty * price;
jTextField19.setText(String.valueOf(totalOil));
}
}
});
t1.start() is in the constructor of the main frame.
The thread primitive methods destroy(), stop(), resume(), and suspend() have been deprecated, so I can't use those. How can I stop and resume a thread now? And if my thread t1 is interrupted, how can it be resumed or run again?
Threads cannot be re-used. For tasks that require to be executed on a separate thread at different times, use a single thread executor.
It seems like you need a worker thread. Since standard threads are not reusable without extra work, we use worker threads to manage tasks that should be executed multiple times.
ExecutorService executors = Executors.newSingleThreadExecutor();
With this, you can reuse a single thread to execute code multiple times. It also allows you to make asynchronous callbacks using Future like this:
class Demo {
static ExecutorService executor = Executors.newSingleThreadExecutor();
public static void main(String[] args) {
Future<String> result = executor.submit(new Callable<String>() {
public String call() {
//do something
return "Task Complete";
}
});
try {
System.out.println(result.get()); //get() blocks until call() returns with its value
}catch(Exception e) {
e.printStackTrace();
}
}
}
You can now re-use executor for the task that you want. It accepts Runnable through it's execute(Runnable) method.
I see you're using Swing. Post all swing code to the Event Dispatch Thread using EventQueue.invokeLater(Runnable). getText() and setText() should be called on the Event Dispatch Thread to avoid inconsistancies.
How can I stop and resume a thread now?
You can't. Instead, you need to make your thread stop and resume itself. For example:
private boolean wake;
public synchronized void wakeup() {
this.wake = true;
this.notify();
}
public void run() {
while ( !t1.isInterrupted() ) {
// do stuff ...
wake = false;
synchronized (this) {
while (!wake) {
try {
this.wait();
} catch (InterruptedException ex) {
t1.interrupt(); // reset the interrupted flag
}
}
}
}
}
When some other thread wants to get this one to do something, the calls the wakeup() method on the extended runnable object.
And if my thread t1 is interrupted, how can it be resumed or run again?
As you have written it, No. Once the thread returns from the run() method call, it cannot be restarted. You would need to create and start a brand new Thread.
However, what you are trying to do is unsafe. As #Erwin points out, it is not safe for the t1 thread to be calling methods on Swing objects such as jTextField19. You should only call methods on Swing objects from the Swing event dispatching thread.
Reference:
Concurrency in Swing
Hello i'm new in Android(Java), and i have a problem with the use of thread
I define e new Thread timed (every 5 seconds) inside a class of my android Project.
The "mContinueThread" variable is used to cicle every 5 seconds
r = new Runnable() {
public void run() {
while (mContinueThread) {
try {
Thread.sleep(MILLISEC_BEFORE_RELOAD);
mHandler.sendEmptyMessage(GET_TRACKING);
}
catch (Exception e)
{
}
}
}
};
t = new Thread(r);
In the CLass there is a method StartTrack() that starts with Thread
public void StartTrack()
{
mContinueThread=true;
if (!mThreadIsStarted)
{
mThreadIsStarted=true;
t.start();
}
else
{
}
}
and there is also a method Logout that stop the thread, using the "mContinueThread" variable:
public void LogOut()
{
//STOP THREAD
mContinueThread=false;
....
}
If in the class Logout() method is executed the thread is stopped, but if the StartTrack() method is called again I don't know how to restart the execution of the thread.
Can you Help Me?
You can use AsyncTask in Android. This will get rid of the burden of managing the threads manually. Please visit http://developer.android.com/reference/android/os/AsyncTask.html
You cannot re-start a thread. Once thread is finished execution it will reach the DEAD state. And whatever is DEAD cannot be brought back to life again, neither in real world nor in JAVA world.
You have no way to restart a thread as long as it exited. You can just start a new start.
I solved so:
In my class I just define the Runnable object, but not the new Thread.
In the StartTrack method(), if the thread has not yet been instantiated, I create and start
public void StartTrack()
{
mContinueThread=true;
if (!mThreadIsStarted)
{
mThreadIsStarted=true;
t = new Thread(r);
t.start();
}
}
In the "LogOut()" method, if Thread is started, I Stop It, and I set It to Null.
In this way, at the next call of "StartTrack()" method, I can recreate it again
public void LogOut()
{
mContinueThread=false;
if (mThreadIsStarted)
{
//THREAD STOP
mContinueThread=false;
mThreadIsStarted=false;
//THREAD TO NULL
t=null;
}
...
}
I suggest it's better to use something like Timer instead of thread.
http://developer.android.com/reference/java/util/Timer.html
Then you can do cancel() if you want to stop execution of your task
and resume it by scheduling new one.
Can I do something like this in Java:
protected Runnable getRunnable(final int seconds) {
Runnable runnable = new Runnable() {
public void run() {
sendData();
try {
Thread.sleep(seconds * 1000);
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
};
return runnable;
}
And then:
protected void startTimer(int seconds) throws InterruptedException,NullPointerException {
Thread thread = new Thread(getRunnable(seconds));
thread.start();
}
Is the aforementioned process safe??
In the comments you say
All I'm trying to do is to execute sendData() method every a specific amount of seconds(i.e. every 15 seconds)
Then use a built-in Timer which will organise that for you, for example:
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
Runnable r = new Runnable() {
#Override
public void run() {
sendData();
}
};
ScheduledFuture<?> future = scheduler.scheduleAtFixedRate(r, 0, 15, TimeUnit.SECONDS);
//when you want to cancel the scheduled task
future.cancel(true);
//and before you leave your program, don't forget to call:
scheduler.shutdown();
Yes it is safe (assuming sendData itself is safe), but I'm not sure exactly what you expect it to do. Your code as written will create a new thread that will immediately call sendData(), then after sendData returns the thread will sleep for a number of seconds and then terminate without doing anything else (so the sleep is pointless, other than preventing the JVM from exiting or the Runnable or its containing object from being garbage collected until the sleep is finished). If you want it to wait before calling sendData then you need to swap things around a bit.
Have you tried it ? The answer is that it does work. Runnable is an interface implemented by an Object (an anonymous class in your example above), and you can pass it around / reference it just like any other object.
Note that because the above is an inner class, you'll have an implicit reference to the outer (surrounding) class.
When i start some thread in my program, everything else is stopped.
This is my Thread code...
static Thread b1 = new Thread(new Builders());
b1.run();
System.out.println("done");
This is the class Builders.
public class Builders implements Runnable {
static boolean busy=false;
Random r = new Random();
public void run() {
try{
busy=true;
System.out.println("ready");
Thread.sleep(9999);
busy=false;
System.out.println("done");
}
catch(Exception e){
}
}
}
When I run the program , the thread is started and the program wait for the end of the thread. I thought the main point of the threads is that the code can run simultaneously. Could someone please help me understand what I'm doing wrong.
That's because threads are started with start(), not run(), which simply calls the run method on the current thread. So it should be:
static Thread b1 = new Thread(new Builders());
b1.start();
System.out.println("done");
This is because you are not starting a thread - instead, you are executing thread's code synchronously by calling run(); you need to call start() instead.
Better yet, you should use executors.
You need to call the start() method. The internal code of Thread will start a new operating system thread that calls your run() method. By calling run() yourself, you're skipping the thread-allocation code, and just running it in your current Thread.
This code creates and starts a thread:
new Thread() {
#Override
public void run() {
try { player.play(); }
catch ( Exception e ) { System.out.println(e); }
}
}.start();
I'd like to modify this code so that the thread only starts if there are no other threads open at the time! If there are I'd like to close them, and start this one.
You can create an ExecutorService that only allows a single thread with the Executors.newSingleThreadExecutor method. Once you get the single thread executor, you can call execute with a Runnable parameter:
Executor executor = Executors.newSingleThreadExecutor();
executor.execute(new Runnable() { public void run() { /* do something */ } });
My preferred method would be putting a synchronized keyword on the play method
synchronized play()
synchronized methods will lock the function so only one thread will be allowed to execute them at a time.
Here's some more info
https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
you could create a static data member for the class(where threading takes place) which is incremented each time an object of that class is called,read that and u get the number of threads started