Continue executing a thread while another thread is running in java - java

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.

Related

How to make Thread in android run infinitely

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)

How to call a function in java if the program doesn't return anything after n seconds

I have a function like this:
public boolean doLogin() {
try {
somemethodForLogin();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
In this case I want to return false or throw an exception if somemethodForLogin() takes more time than expected, say 8 seconds. How can I do this?
I added something like this just before somemethodForLogin():
new java.util.Timer().schedule(
new java.util.TimerTask() {
#Override
public void run() {
System.out.println("Returning after 8 seconds wait");
}
}, 8000);
But it comes into this always, even if the call is success.
You can use a completable future to call the login, then retrieve the result with a timeout:
try {
CompletableFuture.runAsync(() -> somemethodForLogin())
.get(8, TimeUnit.SECONDS);
return true;
}catch(TimeoutException timeoutException) {
//Timeout handline here
return false; //or call other function
}
The above lambda is a Supplier rather than a Runnable.
CompletableFuture's get method is documented with the following:
Waits if necessary for at most the given time for this future to complete, and then returns its result, if available.
TimeoutException - if the wait timed out
EDIT:
The above is using CompletableFuture<Void> as the call is taking a Runnable. If somemethodForLogin() returns a value, you can use the same API, but calling supplyAsync:
Object loginResult = CompletableFuture.supplyAsync(() -> somemethodForLogin())
.get(8, TimeUnit.SECONDS);
//Just change the return types accordingly.
So i have just created a sample program to solve your problem .I think that it works as expected but you could also tried it at your side.
I have explained the code in the code comments so it is not a code dump.
class Test
{
// your do logic method
public boolean doLogic()
{
try{
//New Thread for logic();
Thread t1=new Thread(new Runnable() {
public void run() {
// calling your logic function in a new thread
try{login();}catch(Exception e){e.printStackTrace();}
}
});
t1.start();
//Making the current thread to sleep for 8 seconds.
Thread.sleep(8000);
//check if t1 has ended within 8 seconds, and then return the required value
if(!t1.isAlive())
return true;
else
return false;
}
catch(Exception e)
{
e.printStackTrace();
return false;
}
}
void login()throws Exception
{
Thread.sleep(9000);//tweak this value sleeps the t1 thread for a specific time just to simulate the login function
}
// driver method
public static void main(String args[])
{
System.out.println(new Test().doLogic());
}
}
Both answers allow a possibility for a denial of service attack by repeated login requests. As the executing thread will still continue to execute after 8 seconds, firing repeated login attempts would keep creating threads that would eat away the resources. The CompletableFuture approach would fill up the common pool, which wouldn't keep creating threads, but it would affect every other part of the code that uses the common pool.
What you can do is create a secondary pool with one or just a few connections dedicated to logging in. Set the connection checkout timeout to 8 seconds, and you've got your timeout there right out of the box. Not to mention less competition on the pool that's doing business tasks.

Future cancel(boolean b) method not working when used in GUI application

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.

Running code on the main thread from a secondary thread?

This is a general Java question and not an Android one first off!
I'd like to know how to run code on the main thread, from the context of a secondary thread. For example:
new Thread(new Runnable() {
public void run() {
//work out pi to 1,000 DP (takes a while!)
//print the result on the main thread
}
}).start();
That sort of thing - I realise my example is a little poor since in Java you don't need to be in the main thread to print something out, and that Swing has an event queue also - but the generic situation where you might need to run say a Runnable on the main thread while in the context of a background thread.
EDIT: For comparison - here's how I'd do it in Objective-C:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0UL), ^{
//do background thread stuff
dispatch_async(dispatch_get_main_queue(), ^{
//update UI
});
});
Thanks in advance!
There is no universal way to just send some code to another running thread and say "Hey, you, do this." You would need to put the main thread into a state where it has a mechanism for receiving work and is waiting for work to do.
Here's a simple example of setting up the main thread to wait to receive work from other threads and run it as it arrives. Obviously you would want to add a way to actually end the program and so forth...!
public static final BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
public static void main(String[] args) throws Exception {
new Thread(new Runnable(){
#Override
public void run() {
final int result;
result = 2+3;
queue.add(new Runnable(){
#Override
public void run() {
System.out.println(result);
}
});
}
}).start();
while(true) {
queue.take().run();
}
}
In case you are on Android, using a Handler should do the job?
new Handler(Looper.getMainLooper()).post(new Runnable () {
#Override
public void run () {
...
}
});
An old discussion, but if it is a matter of sending request to the main thread (an not the opposite direction) you can also do it with futures. The basic aim is to execute something in background and, when it is finished, to get the result:
public static void main(String[] args) throws InterruptedException, ExecutionException {
// create the task to execute
System.out.println("Main: Run thread");
FutureTask<Integer> task = new FutureTask<Integer>(
new Callable<Integer>() {
#Override
public Integer call() throws Exception {
// indicate the beginning of the thread
System.out.println("Thread: Start");
// decide a timeout between 1 and 5s
int timeout = 1000 + new Random().nextInt(4000);
// wait the timeout
Thread.sleep(timeout);
// indicate the end of the thread
System.out.println("Thread: Stop after " + timeout + "ms");
// return the result of the background execution
return timeout;
}
});
new Thread(task).start();
// here the thread is running in background
// during this time we do something else
System.out.println("Main: Start to work on other things...");
Thread.sleep(2000);
System.out.println("Main: I have done plenty of stuff, but now I need the result of my function!");
// wait for the thread to finish if necessary and retrieve the result.
Integer result = task.get();
// now we can go ahead and use the result
System.out.println("Main: Thread has returned " + result);
// you can also check task.isDone() before to call task.get() to know
// if it is finished and do somethings else if it is not the case.
}
If your intention is to do several stuff in background and retrieve the results, you can set some queues as said above or you can split the process in several futures (starting all at once or starting a new one when needed, even from another future). If you store each task in a map or a list, initialized in the main thread, you can check the futures that you want at anytime and get their results when they are done.
You may want to use the 'even dispatching thread' where most event driven things happen. If you are using swing then:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Your code here.
}
});
Or create a class that implements Runnable and pass it into invokeLater().
If you're using JavaFX, which I highly recommend, then you can use
Platform.runLater(new Runnable() {
#Override
public void run() {
alert(text);
}
});
from within your non-UI thread, and the runnable will executed from the UI thread on return from your thread.
A little late to the party but I think that my approach is a little bit different.
Modifying Affe's solution a little bit
public static final BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
public static void main(String[] args) {
Thread myThread = new Thread(
() -> {
String name = Thread.currentThread().getName();
System.out.println("initial current thread " + name);
queue.add(() -> System.out.println(Thread.currentThread().getName()));
});
myThread.setName("background thread");
myThread.start();
try {
myThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
while (!queue.isEmpty()) {
try {
queue.take().run();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
output
initial current thread background thread
main

Starting and Stopping Threads with Buttons

I have what I thought was a simple problem, which I have yet to find a good solution to: I would like to be able to pause and unpause the activity taking place in a thread, by hitting a button on a Swing interface panel.
Specifically, I would like to use one thread to take in audio frames in real time; a second thread to perform magic processing on those frames; and a third thread to serialize the results and send over a socket somewhere else. The kicker is that depending on the brand of magic we employ, the processing in the second thread might take longer per frame to perform than the actual data collection, and the data might pile up after a while.
As a very crude prototype workaround we thought we'd add a GUI with a button to turn the audio collection process on and off and a status bar (to be implemented later) so that a user could sort of keep an eye on how full the buffer (a linked blocking queue) happened to be.
This is harder than I anticipated. I've stripped the problem down to a toy version: A linked blocking queue that can store 50 Integers, a GUI, two threads (adding to and removing from the queue at different rates) and a Token object wrapped around a boolean. It looks like this, and it sorta works:
Test.java
public class Test {
public static void main(String[] args) throws IOException {
Token t1 = new Token();
Token t2 = new Token();
LinkedBlockingQueue<Integer> lbq = new LinkedBlockingQueue<Integer>(50);
startFill sf = new startFill(t1, lbq);
startEmpty se = new startEmpty(t2, lbq);
TestUI testUI = new TestUI(t1, t2, lbq);
testUI.setVisible(true);
sf.start();
se.start();
}
}
TestUI.java
public class TestUI extends JFrame implements ActionListener {
private JToggleButton fillStatus, emptyStatus;
public boolean filling, emptying;
public Token t1, t2;
public LinkedBlockingQueue<Integer> lbq;
public TestUI(Token t1, Token t2, LinkedBlockingQueue<Integer> lbq) {
this.t1 = t1;
this.t2 = t2;
this.lbq = lbq;
initUI();
}
public synchronized void initUI() {
JPanel panel = new JPanel();
panel.setLayout(null);
filling = false;
fillStatus = new JToggleButton("Not Filling");
fillStatus.setBounds(20, 20, 150, 25);
fillStatus.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
if (filling == false) {
fillStatus.setText("Filling");
} else {
fillStatus.setText("Not Filling");
}
filling = !filling;
t1.flip();
System.out.println("fill button press");
}
});
// Similar code for actionListener on Empty button, omitted
panel.add(fillStatus);
panel.add(emptyStatus);
add(panel);
setTitle("Test interface");
setSize(420, 300);
setLocationByPlatform(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public void actionPerformed(ActionEvent e) {
}
}
startFill.java
public class startFill extends Thread {
public Token token;
public LinkedBlockingQueue<Integer> lbq;
public startFill(Token token, LinkedBlockingQueue<Integer> lbq) {
this.token = token;
this.lbq = lbq;
}
public void run() {
int count = 0;
while (true) {
while (!token.running()) {
try {
sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
while (token.running()) {
try {
lbq.put(count);
System.out.println("queue size = " + lbq.size());
count++;
sleep(100);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
}
}
There is also a startEmpty.java that works about the same way, and a Token.java that's a wrapper for a boolean state variable, omitted for merciful brevity.
So that works, but at the expense of polling in the while (!token.running()) loop.
I tried using Locks and Conditions, but failed, always getting IllegalMonitorStateExceptions.
And I looked at this similar question and managed to get that working, but at the expense of using the yield() method which apparently differs significantly between Java 5 and Java 6, and seems to be highly discouraged.
So my question: Is there some correct, or significantly better way to do what I am trying to do? It seems like there should be a way to make this happen without the polling and with reliable methods.
Update: I'm not sure I can get around the issue of controlling the audio capture loop in some way for the application. Whether it is a human pressing a button, or internal logic making decisions based on some other factors, we really need to be able to shut the darn thing down and bring it back to life on command.
Instead of handling the synchronisation between your 3 worker processes by hand via a GUI, you could also setup a factory lineup between the workers:
add 2 queues between your workers
block your threads on queue-state conditions;
readers (consumers) block on empty queue
writers (producers) block when the queue is full (say 2n messages where n is the number of consumers for that queue.)
wait() on a queue to block your thread and notifyAll() on that queue after adding or removing a message from a queue.
A setup like this automatically slows down producers running faster than their consumers.
Why dont you implement ArrayBlockingQueue.
Its Better use ArrayBlockingQueue class which is present in java.util.concurrent package, which is Thread Safe.
BlockingQueue<String> queue = new ArrayBlockingQueue<String>(100);
Here is one way to do what I was trying to do: Properly use wait() and notify(), synchronized on the Token objects, like such:
startFill.java run() method
public synchronized void run() {
int count = 0;
try {
// token initializes false
// wait until notification on button press
synchronized (token) {
token.wait();
}
// outer loop
while (true) {
// inner loop runs as long as token value is true
// will change to false on button press
while (token.running()) {
lbq.put(count);
System.out.println("queue size = " + lbq.size());
count++;
sleep(100);
}
// wait until notification on button press, again
synchronized (token) {
token.wait();
}
}
} catch (InterruptedException e2) {
e2.printStackTrace();
}
}
TestUI.java ActionListener:
fillStatus.addActionListener(new ActionListener() {
// t1 was initialized false
public void actionPerformed(ActionEvent event) {
if (filling == false) {
fillStatus.setText("Filling");
// if false, change t1 status to true
t1.flip();
// and send the notification to the startFill thread that it has changed
synchronized (t1) {
t1.notify();
}
} else {
fillStatus.setText("Not Filling");
// if true, change t1 status to false
t1.flip();
// no notification required due to polling nature of startFill's active thread
}
filling = !filling;
System.out.println("fill button press");
}
});
This works rather nicely, without polling while the thread is turned off.
My initial attempts at this failed due to bad syntax-- I neglected the synchronized (token) {...} context block around the wait() and notify() statements.

Categories

Resources