I am just not able to figure out the cause of this issue.
Problem :
1) I am using a Thread.Sleep function to set the timer for my application.
2) Now as soon as user enter the webPage the timer starts, if user clicks any link the timer(thread) is stopped and then new timer starts.
3) If their is no activity for say 3 seconds, timer ends and with it workflow associated with the webpage ends too.
Code :
DownloadSummariesPage.java
public DownloadSummariesPage(){
abc = new SimpleThread(this);
Link<Void> link = new Link<Void>("downloadSummaryLink") {
public void onClick() {
boolean threadStatus = abc.checkStatus();
if (threadStatus) {
abc.interrupt();
abc.stop();
abc = new SimpleThread(DownloadSummariesPage.this);
abc.start();
}
else
{
LOG.debug("thread is dead now");
endWorkflow();
LOG.debug("ending the workflow");
setResponsePage(MenuPage.class);
}
}
};
abc.start();
}
public void endWorkflow() {
abc.interrupt();
abc.stop();
boolean downloadReport = false;
LOG.debug("before action 201 inside endworkflow");
Map<String, Serializable> inputs = new HashMap<String, Serializable>();
inputs.put("downloadReport", downloadReport);
try {
wf.doAction(id, 201, inputs);//do not worry about this its for workflow
String empty = "";
populateDownloadReportDatabase(empty);
setResponsePage(MenuPage.class);
} catch (Exception e) {
LOG.debug("Exception while performing 201 workflow, getControlCancel "
+ e);
}
}
}
My next class which creates thread is
SimpleThread.java
class SimpleThread extends Thread {
private static final Logger LOG = Logger.getLogger(SimpleThread.class);
boolean stillActive = true;
DownloadSummariesPage dsp;
SimpleThread(DownloadSummariesPage dp) {
this.dsp = dp;
}
public void run() {
// 5sec timer
LOG.debug("inside run method");
try {
Thread.sleep(3000);
stillActive = false;
} catch (InterruptedException e) {
LOG.debug("Exception in thread " + e);
e.printStackTrace();
}
LOG.debug("before endworkflow");
dsp.endWorkflow();//so this is what i actually want to do...
LOG.debug("at the end of simplethread");
}
public boolean checkStatus() {
return stillActive;
}
}
Cases :
1) Whats Happening : User logs in thread sleeps, user click a link thread stops and creates a new one if user again click it happens again and now if user do not do anything for 3 seconds, stillAlive variable in SimpleThread class is set to false and when now user click its ends the workflow perfectly...
2) What i want : if user logs in thread starts, and if their is no activity by the user stillAlive variable is set to false and dsp.endWorkflow(); statement now should end the workflow. right ? but it just stops after reaching inside the endWorkflow() function and do not actually end the workflow...
Hope you get this, I tried my best to make it understandable. Thanks for your time..
I appreciate any help..
So there are some strange things here.
first assume the thread sleep without any interruption for 3 sec, so it will call the dsp.endWorkflow() where you call it again from the onClick method.
second the stillAlive flag should be volatile
boolean volatile stillActive = true;
The possible error/bug would raises by this section.
if (threadStatus) {
abc.interrupt();
abc.stop();// you cannot get to this like just after interrupt, maybe thread abc goes first
abc = new SimpleThread(DownloadSummariesPage.this);
abc.start();
}
because assume when thread is sleeping you interrupt it, then stop it, but this is possible that thread finishes it's work just after you interrupt it (before you stop it). so this is better to just stop it, or return when thread reached the catch.
try {
Thread.sleep(3000);
stillActive = false;
} catch (InterruptedException e) {
LOG.debug("Exception in thread " + e);
e.printStackTrace();
return;//////give up the rest work. so you don't need to call the stop too.
}
And the error is here
assume that user don't click the cancel, or new download, and thread just finishes its sleeping and call the dsp.endWorkflow(), so what is going on this method?
public void endWorkflow() {
abc.interrupt();
abc.stop();//error here!
boolean downloadReport = false;//this is unreachable
}
Just look, you are calling this method by abc thread, and the error is that you are killing the thread just inside the method, before you set the downloadReport to false. so it may would be like this.
public void endWorkflow() {
boolean downloadReport = false;//this is unreachable
abc.interrupt();
abc.stop();//error here!
}
I hope I could some help.
Related
tl, dr;
I have a GUI thread that creates an object of another class (the seconds class has implemented Runnable, but here we don't execute the run() method, instead, we call a normal method) and calls a method. In that method, the first thread (current thread) is called again (to show sth on the LCD), then sends some data to the Internet, and waits 3 seconds for the server response. The problem is that the information is printed after 3 seconds. I know about the stack and program counter, but I wonder if there is another option that I can do my job.
I have the main method, which runs 3 threads (for short, I just write the requisite code. Tell me to add more, if needed):
public static void main(String[] args) throws UnknownHostException, InterruptedException {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
GUI.getInstance().setVisible(true); //GUI is singleton, using swing and JFrame
} catch (Exception e) {
e.printStackTrace();
}
}
});
MQTTConnection.getInstance().tryToConnect(); //It's the connection class, which has a thread (the thread is handled by a library that keeps the connection alive. I have no threads there) and is a singleton too.
Thread t1 = new Thread(new SendDataThread()); //A thread which sends some data every 20 seconds.
t1.start();
}
And in SendDataThread, I have a function that creates some random data and sends them (using the MQTTConnection class).
This is the SendDataThread:
public class SendDataThread implements Runnable {
public void sendLog() {
boolean serverOnline = false;
StringBuilder data = new StringBuilder();
data.append(createData());
GUI.getInstance().printNeutral(data.toString()); //Prints BLACK on a `JTextPane`
if(MQTTConnection.getInstance().publishLog(MQTTConnection.getInstance().MQTT_PUBLISH_ESP_SEND_LOG, data.toString())) //This line has a 3 second timeout. If the server doesn't respond, it will return false. I've added the 3 seconds timeout too. Please continue reading.
serverOnline = true;
if(serverOnline)
GUI.getInstance().printOK("Server Submitted"); //Prints in GREEN
else
GUI.getInstance().printProblem("Check your connection!"); //Prints in RED
GUI.getInstance().printNeutral("-------------------------------------------------");
}
#Override
public void run() {
while(true) {
sendLog();
try {
Thread.sleep(20000); //sleeps 20 about seconds
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//.....
}
And this is the 3 seconds timeout method, in MQTTConnection:
boolean publishLog(String topic, String data){
mqtt_responds = false;
publish(topic, data);
System.out.println("MQTT is connected");
long lastTime = System.currentTimeMillis();
while(System.currentTimeMillis() - lastTime < callback_timeout) {
if(mqtt_responds){
mqtt_responds = false;
System.out.println("Server submitted");
return true;
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Timeout");
return false;
}
Till now, everything work right. The problem starts where I have a button in the GUI class, which the user can manually send random logs:
JButton sendLogBtn = new JButton("Send Log");
sendLogBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
SendDataThread sdt = new SendDataThread();
sdt.sendLog();
}
});
sendLogBtn.setBounds(10, 331, 89, 23);
panel.add(sendLogBtn);
This button creates an object of SendDataThread and calls the sendLog() method. The issue happens here: after sendLog() is called, sendLog(), calls this GUI thread again:
--> GUI.getInstance().printNeutral(data.toString()); //Prints BLACK on a `JTextPane`
But the log is printed after 3 seconds (After the sendLog() method has finished working, the timeout!)
How can I fix this?
In the button's actionPerformed you are calling sendLog. sendLog does exactly what you said, ie reports some logs and waits about 3 seconds (assuming callback_timeout is about equal to 3000).
To fix this, you need to make sure that the 3sec blocking is not on the EDT and also to make sure that the logs are instead posted on the EDT.
As a quick workaround you can do:
sendLogBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
new Thread(() -> new SendDataThread().sendLog()).start();
}
});
and then, as always, post your logs in the EDT like for example:
SwingUtilities.invokeLater(() -> GUI.getInstance().printNeutral(...));
AND
SwingUtilities.invokeLater(() -> GUI.getInstance().printProblem(...));
AND
SwingUtilities.invokeLater(() -> GUI.getInstance().printOk(...));
As for the question in your comment, I don't really understand what you are asking, but I should say that (as far as I know) the EDT is a Thread where all the Swing code is (and should be) posted on for execution. This way the Swing code does not have to be synchronized, because all GUI related stuff is executed sequentially (on the EDT). AWT for example was not intended to be single threaded as far as I know. Swing is however single threaded.
Runnable updateSeekbar=new Runnable() {
#Override
public void run() {
try{
while (true) {
if (!isPlayerDead) {
Log.d("Threads", "Thread is running successfully.");
int progress=mediaPlayer.getCurrentPosition();
seekBar.setProgress(progress);
Log.d("Seekbar",seekBar.getProgress()+"");
Log.d("MediaProgress",mediaPlayer.getCurrentPosition()+"");
String s=modifyTime(mediaPlayer.getCurrentPosition() / 1000 / 60) + ":" + modifyTime((mediaPlayer.getCurrentPosition() / 1000) % 60);
progressTime.setText(s);
}
}
}
catch (Exception e){
e.printStackTrace();
}
}
};
Executor executor=new Executor() {
#Override
public void execute(Runnable command) {
Thread thread=new Thread(command);
thread.start();
}
};
executor.execute(updateSeekbar);
Actually the problem is that the thread dies before the mediaplayer can send updated position. I have made the thread in an endless while loop but still it dies. How can I make it run infinitely till the activity gets destroyed.
The thread only runs for a couple of seconds and then dies. I want it to run infinitely till the activity gets destroyed. All suggestions are welcome.
when mediaPlayer isn't in proper state and you try to call some improper method then some Exception may be thrown, and you are catching it OUTside while(true) loop. try to move try{}catch inside while(true), then your Thread will run infinitely
#Override
public void run() {
while (true) {
try{
if (!isPlayerDead) {
// current code
}
}
catch (Exception e){
e.printStackTrace();
}
SystemClock.sleep(20); // some bonus line
} // end of while
}
btw. give some rest for UI between iterations, e.g. by putting SystemClock.sleep(20); after every calculation (last line before closing bracket). you don't need so often progress refreshing, in current code it may happen even few times more often than system is capable to draw (in most often 60Hz case)
I have the following code:
public class Cancelling {
public static void main(String args[]) {
ToBeCancelled tbc = new ToBeCancelled();
ForkJoinPool pool = new ForkJoinPool(1);
Future<?> future = pool.submit(tbc);
try {
Thread.sleep(3000);
} catch (InterruptedException ie) {}
future.cancel(true);
if (future.isCancelled())
System.out.println("The task has been cancelled");
}
}
With the ToBeCancelled class being:
public class ToBeCancelled implements Runnable {
public void run() {
try {
Thread.sleep(5000); // should throw exception here
} catch (Exception e) {
return; // should exit
}
System.out.println("I should never be able to print this");
}
}
The main thread should start, wait for 3 seconds, and then cancel the ToBeCancelled task by using future.cancel(true). It then should print The task has been cancelled, while the task never gets to print its message.
At least, this is what happens when I start it from console.
As I start it from a GUI application with a TextArea where the output is redirected to, that's not the case. The main method does print The task has been cancelled, but the task also prints I should never be able to print this.
This is driving me insane. From what I understand the task should receive its cancel command while on the Thread.sleep(5000) method, which would fire an exception that is consequently caught and makes the thread return. But it doesn't happen and yet the main thinks it has been cancelled. It's like the cancel method is completely ignored by the task.
I've tried everything I could think of, checking on the returned value of cancel, making the task wait longer, using Thread.currentThread().isInterrupted(), but nothing works.
I feel like I'm missing something really simple, but I just can't find what it is. Any idea?
In case anyone thinks it might be something on the GUI application, this is the method that starts the program:
public static void StartProgram(String name) {
try {
Method m = Class.forName(name).getDeclaredMethod("main",String[].class);
Object[] args = new Object[1];
String s[] = new String[2];
s[0] = tf1.getText();
s[1] = tf2.getText();
args[0] = s;
t = new Thread(new ProgramStarter(args, m));
t.start();
} catch (Exception e) {
e.printStackTrace();
}
}
With ProgramStarter being:
public class ProgramStarter implements Runnable {
private Object[] args;
private Method m;
public ProgramStarter(Object args[], Method m) {
this.args = args;
this.m = m;
}
public void run() {
try {
m.invoke(null, args);
} catch (Exception e) {
e.printStackTrace();
}
}
}
The problem is that your verification is wrong. You think that your code works when running from the console but in fact, it fails in all cases. When running from the console your main thread ends after the attempt to cancel the future and the JVM will terminate as there are only daemon threads left in the JVM. Due to the JVM termination you don’t notice that the cancellation did not work.
When adding a sleep at the end of your main method to delay the JVM termination you will notice that "I should never be able to print this" is printed when running from the console as well. So the only difference between GUI and console version is that the running Event Dispatch Thread prevents the JVM from terminating so you see that it doesn’t work.
The bottom line is: don’t use ForkJoinPool unless you have a reason for this.
Since you just want submit to a simple single-background-thread executor, you can create the executor using Executors.newFixedThreadPool(1). This has less unexpected behavior: it’s thread is non-daemon by default and it’s Future will cancel with interruption as expected.
I am new to Java. I tried to write a program to check database status (overloaded or not).
CODE:
package com.test.service;
import java.util.LinkedList;
import java.util.List;
public class PersonImpl {
public PersonService personService;
public void InsertPersonDetails(Person person) {
if(personService.isOverLoaded()) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
//pass control to dao
}
}
}
Here I will get boolean from isOverLoaded. If isOverLoaded value is yes then we should stop passing control to dao for few seconds and then check isOverLoaded method again.
Help would be appreciated :)
Your code looks work fine.
if(personService.isOverLoaded())
{
try {
Thread.sleep(5000);
//Any other code to execute after 5 min execution pause.
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
//pass control to dao
}
Thread.sleep(5000) pause your execution for 5 sec and resume it again. If your have any code after this statement than it will executed after 5 sec of pause if not than it will execute code written after your if/else is completed.
If you want to continue check database overload status than you need to continue execute your function personService.isOverLoaded() after every 5 sec to check your database status.
For Example :
while(personService.isOverLoaded())
{
try {
Thread.sleep(5000);
//Any other code to execute after 5 min execution pause.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//pass control to dao
I would go for an ScheduledExecutorService. Create a thread and as long as isOverloaded() returns true re schedule the execution.
As an alternative you could a java.util.concurrent.BlockingQueue to control the flow. You would start the dao as a consumer of the queue in a thread. Your InsertPersonDetails method would then push to the queue from the main thread.
Can I also point out that it is usual in java to start methods with a lowercase letter so your method would be
public void insertPersonDetails(Person person)
Your code looks ok and should work. But you need to make sure that the boolean value passed by personService.isOverLoaded() is volatile.
Volatile will make sure that value of this boolean flag is not cached by your processing thread.
private volatile boolean flag = false;
public void overLoaded(){
flag = true; // based on some condition
}
public boolean isOverLoaded(){
return flag; // Accessed in your thread
}
I have a certain function in my program that I want to stop on the press of a key. I have a native keyboard hook set up for that purpose. Right now, I call System.exit(0) when that key is detected. However, I don't want to exit the program, just stop that operation and return to where it was called. An example is given below.
public class Main {
public static void main(String[] args) {
System.out.println("Calling function that can be stopped with CTRL+C");
foo(); // Should return when CTRL+C is pressed
System.out.println("Function has returned");
}
}
I've tried putting the call to foo() in a thread so I could call Thread.interrupt() but I want the function call to be blocking, not non-blocking. Also there are blocking IO calls in foo() so I'd rather not deal with interrupts unless it's necessary, because I'd have to deal with ClosedByInterruptException exceptions and that has caused problems before.
Also the body of foo() is very long and has many function calls inside it, so writing if (stop == true) return; in the function is not an option.
Is there a better way to do this than making a blocking thread? If so, how? If not, how would I make a blocking thread?
How about this?
// Create and start the thread
MyThread thread = new MyThread();
thread.start();
while (true) {
// Do work
// Pause the thread
synchronized (thread) {
thread.pleaseWait = true;
}
// Do work
// Resume the thread
synchronized (thread) {
thread.pleaseWait = false;
thread.notify();
}
// Do work
}
class MyThread extends Thread {
boolean pleaseWait = false;
// This method is called when the thread runs
public void run() {
while (true) {
// Do work
// Check if should wait
synchronized (this) {
while (pleaseWait) {
try {
wait();
} catch (Exception e) {
}
}
}
// Do work
}
}
}
(taken from http://www.exampledepot.com/egs/java.lang/PauseThread.html not my own work)