So I'm trying to add multithreading to my app and I'm running into a weird issue. I create a new runnable to handle parsing all the data so that the application doesn't freeze while it's doing so, and then create a new thread to run that runnable. However, when the thread starts and run() gets called, I noticed it never calls onCompleted(). This is weird to me because if I take that exact block of code out of the run() part, it works perfectly.
Can anybody let me know what I'm doing wrong? I'm a bit new to multithreading in Java, so I would really appreciate it.
Runnable parseRunnable = new Runnable(){
#Override
public void run(){
new Request(session, id + "/comments", null, HttpMethod.GET, new Request.Callback() {
#Override
public void onCompleted(Response response) {
try {
JSONArray msgs = response.getGraphObject().getInnerJSONObject().getJSONArray("data");
populateData(msgs);
} catch (JSONException e) {
e.printStackTrace();
}
Request next = response.getRequestForPagedResults(Response.PagingDirection.NEXT);
retrieveMsgs(next);
}
}).executeAsync();
}
};
Thread parseThread = new Thread(parseRunnable);
parseThread.start();
I set a breakpoint at run() and at "new Request" which always gets hit, but when I set breakpoints for onCompleted(), those are never reached.
Your thread will finish when you reach the end of
public void run ()
I'm going to assume you don't get your callback because your thread has already finished since you call executeAsync (which will execute on a separate thread). Removing your thread altogether will probably fix your problem.
Related
I'm using Firebase in an Android app. The app sets up something like a groupchat and allows users to join.
The users get a key and can then connect themselves to the corresponding DatabaseReference.
We need a check whether the key is valid. Therefore, when the group is created, the host automatically adds himself to a list of users. Then all new clients can check if there are entries in the list. If the list is empty, the key is invalid.
This means that I need to wait for the completion of a setValue call.
Firebase has many callbacks that can tell me about this, but they are quite problematic. Sometimes, they simply aren't called.
I've already asked a question about this non-deterministic behaviour here: How to listen for Firebase setValue completion
Now I've found a new problem with those callbacks.
I've changed my infrastructure to an asynchronous setup. All interactions are packaged into Callables and submitted to an ExecutorService. The result is a Future<>. Now, if I want to wait for something to complete, I can just wait on that future. Inside of the Future, I still need to use the Firebase callbacks.
The code is in a wrapper class called DBConnection.
Here is my code for creating a new group (party) :
public Future<DBState> createParty() {
// assert entries
assertState(DBState.SignedIn);
// process for state transition
Callable<DBState> creationProcess = new Callable<DBState>() {
#Override
public DBState call() throws Exception {
lock.lock();
try {
// create a new party
ourPartyDatabaseReference = partiesDatabaseReference.push();
usersDatabaseReference = ourPartyDatabaseReference.child("users");
// try every remedy for the missing callbacks
firebaseDatabase.goOnline();
ourPartyDatabaseReference.keepSynced(true);
usersDatabaseReference.keepSynced(true);
// push a value to the users database
// this way the database reference is actually created
// and new users can search for existing users when they connect
// we can only continue after that task has been completed
// add listeners for success and failure and wait for their completion
// TODO: we need information that this task has been finished
// but no callback seems to work
// onSuccess, onCompletion on the task are not reliable
// and the child and value event listeners on the userDatabaseReference are not reliable, too
final CountDownLatch waiter = new CountDownLatch(1);
usersDatabaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
waiter.countDown();
}
#Override
public void onCancelled(DatabaseError databaseError) {
waiter.countDown();
}
});
Task addingTask = usersDatabaseReference.child(user.getUid()).setValue(true);
addingTask.addOnSuccessListener(new OnSuccessListener() {
#Override
public void onSuccess(Object o) {
waiter.countDown();
}
});
addingTask.addOnCompleteListener(new OnCompleteListener() {
#Override
public void onComplete(#NonNull Task task) {
waiter.countDown();
}
});
try {
waiter.await();
} catch (InterruptedException ex) {
}
connectToParty();
} finally {
lock.unlock();
}
// if we could connect, we are now DBState.Connected,
// otherwise we are still DBState.SignedIn
return state;
}
};
// start process
return executorService.submit(creationProcess);
}
You can use it like this:
Future<DBState> creationFuture = dbConnection.createParty();
try {
creationFuture.get(TIMEOUT, TimeUnit.MILLISECONDS);
} catch (InterruptedException ex) {
throw new AssertionError("there should be no interrupt");
}catch (TimeoutException ex) {
throw new AssertionError("timeout in party creation");
}catch (ExecutionException ex) {
throw new AssertionError("concurrent execution exception");
}
I've written tests for this.
And in the tests, everything works fine. I've executed the canCreateParty test at least a dozen times now.
To make sure, that the callbacks work, I've increased the CountDownLatch to 3 counts and added breakpoints to the countDowns. Every countDown is reached.
But at runtime, no callback is ever called.
None of the breakpoints are reached, the waiting for the future eventually times out.
The strangest part is: I have the firebase console open right next to the emulator. I can see how new parties are created and users are added. Both for the tests and at runtime, the party creation works just as expected and a new user is added.
Why am I getting no callback at runtime ?
The reason is that Firebase always calls its callbacks from the main thread.
The "main" thread in my tests is called something like "junittestrunnerXXX". And Firebase creates a new thread called "main" to call the callbacks.
At runtime, the "main" thread is the actual "main" thread. If I call get() on that, it is blocked for good. Firebase checks if this thread exists and since it already exists and since it is blocked, nothing happens.
i am writing code from online to create a chat application. After trouble shooting my program to find out why it is not working I have discovered that the code inside my run method here is not being reached. here is the snippet of code
public void listen()
{
listen = new Thread("Listen") {
public void run()
{
writeMessage("Working in here");
while (true) {
String message = client.receive();
if (message.startsWith("/c/")) {
client.setID(Integer.parseInt(message.substring(3, message.length())));
writeMessage("Successfully connected to server" + client.getID());
}
}
}
};
}
It is reaching the listen method itself, because if i use the write message command before i declare the thread, it prints out the message for me, any idea from looking at this why it will not enter any further?
Thanks
Calling start() on your Thread would do it:
public void listen()
{
listen = new Thread("Listen") {
public void run()
{
writeMessage("Working in here");
while (true) {
String message = client.receive();
if (message.startsWith("/c/")) {
client.setID(Integer.parseInt(message.substring(3, message.length())));
writeMessage("Successfully connected to server" + client.getID());
}
}
}
};
listen.start(); // <-- Add this line
}
Also, you typically don't want to extend Thread (which you are doing here with an anonymous class). Usually you'll want to create a Runnable and pass that to Thread's constructor instead:
Runnable r = new Runnable() {
#Override
public void run()
{
// Do some work here
}
};
Thread listen = new Thread(r, "Listen");
listen.start();
Or even better, use an Executor, there aren't many good reasons to create your own Thread objects.
Certainly working with appropriate Execotor or even better ExecutorService is more appropriate way of working with threads today. Read about it here. But if you insist on working the old way then you need to invoke start() method of your thread. Methods start() and run() do the same thing, only run() execute your thread sequentially i.e. in the same thread where you invoked it and start() actually starts a new thread where your code is executed which is what you wanted in the first place
I'm starting a thread which loops indefinitely until a certain event occurs. The problem is, I want to start this thread, and then return to the normal execution of my program. However, after starting the thread, the code seems to get stuck.
Code:
public void init()
{
Runnable thread = new Runnable()
{
public void run()
{
while(something)
{
//do something
}
}
};
System.out.println("Starting thread..");
new Thread(thread).run();
System.out.println("Returning");
return;
}
When I start this, I get the output "Starting thread" but I don't get "returning" until the conditions for the while loop in the run() stop being true.
Any ideas how I can make it work asynchronously?
Use start rather than run to start a Thread. The latter just invokes the run method synchronously
new Thread(thread).start();
Read: Defining and Starting a Thread
You may try this in your code:-
new Thread(thread).start();
like:-
public void init()
{
Runnable thread = new Runnable()
{
public void run()
{
while(something)
{
//do something
}
}
};
System.out.println("Starting thread..");
new Thread(thread).start(); //use start() instead of run()
System.out.println("Returning");
return;
}
You want to call new Thread(thread).start() instead of run().
Are you sure about your approach? You say:
The thread should loop indefinitely until certain event occurs.
that's an enormous loss of computational resource, the program is principally bound to get slow & fail. You may want to put the thread in wait() mode and catch InterruptedException to wake it up upon occurrence of your event of interest. If this preliminary understanding of what you are trying to accomplish is true then Id' strongly suggest you to revise your approach. Computing resource is expensive, don't waste it in relentless looping.
I have a method that does some printing and I want the task to run on another thread (not on the EDT) because it might be creating a large file and I dont want the long process to freeze the GUI. The execution works perfectly on the EDT (with GUI freezing of course - which isn't desired), but when invoked on a different thread, it just doesn't execute. Here goes the method;
buildReceipt(itemList, method);
Where;
itemList is an ArrayList used to populate the receipt, and
method is an enum Type that determines whether to make the output a .pdf File or Send it directly to a Printer
The code above produces the document nicely when executed on the EDT but when I tried making it a background task using doInBackground() method of SwingWorker , it just didn't do anything at all; Then I got curious and tried the following;
Thread thread = new Thread(new Runnable(){
#Override
public void run()
{
buildReceipt(itemList, method);
}
});
thread.start();
and still, nothing happened......... More funny and confusing is the fact that I have even tried SwingUtilities.InvokeLater & SwingUtilities.InvokeAndWait (which by documentation run on the EDT) but still to no avail.
I have searched as many Stack Overflow related questions as I could, but none addresses my strange problem. I really need help on this one. Been stuck since yesteray?!?!?!
EDIT:
In Respose to Jean Waghetti; here's briefly what happens inside buildReceipt
private boolean buildReceipt(ArrayList<Sales> itemList, PrintMethod method)
{
boolean built = false;
if(!itemList.isEmpty())
{
InvoiceDesign design = new InvoiceDesign(itemList);
try
{
JasperReportBuilder report = design.build();
if(method.equals(PrintMethod.PDF))
{
appManager.connectToDB();
File fileDir = appManager.getReceiptsDir();
appManager.disconnectDB();
FileOutputStream fos = new FileOutputStream(fileDir);
report.toPdf(fos);
fos.close();
built = true;
}
else if(method.equals(PrintMethod.PRINTER))
{
report.print(true);
built = true;
}
}
catch(IOException e)
{
e.printStackTrace();
}
catch (DRException e)
{
e.printStackTrace();
}
}
return built;
}
So basically your item list is empty hence it never executes the code in the IF condition in that method.
In my button execution, I am calling 2 methods.
plotButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
startPrinterListOperation();
showAplotPlotterDialog();
}
});
The startPrinterListOperation(); takes some time to complete its task. But I do not want the method showAplotPlotterDialog(); to run until the first one has completed. So I am trying to use thread management to achieve this. Here is what I have tried.
plotButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
Thread t = new Thread() {
public void run() {
startPrinterListOperation();
}
};
t.start();
try {
t.join();
}
catch (InterruptedException e1) {
e1.printStackTrace();
}
showAplotPlotterDialog();
}
});
But the second method stills starts before the first one has finished.
Extending on my comment: Seems like startPrinterListOperation launches an asynchronous operation and finishes instantly, evidented by the join succeeding.
If the launched async op is out of your control, then you might be able to observe it finishing via some callback, polling, etc. Then you may employ something like the following in startPrinterListOperation:
void startPrinterListOperation() {
final CountDownLatch c1 = new CountDownLatch(1);
launchTheAsyncOp(new SomeCallback() {
void x() {
c1.countDown();
}
});
try {
c1.await(999, TimeUnit.SECONDS)
}
catch (InterruptedException e) {
throw new MyRuntimeException("user didn't finish the op in 999 seconds, fail");
}
}
I would not bother with threads, this will just make your program overly complicated.
Can you edit the startPrinterListOperation() method?
I would instead add showAplotPlotterDialog(); to the end of the startPrinter method, and the last last thing the method does.
Answering your general question in the title, you have a master thread that calls your two methods directly, so that the second method waits for the first method to complete.
I understand that in your specific case, the first method runs for a while, and you would prefer that the user not have to wait.
You should call a generatePrinterList() method in a separate thread while you're constructing the GUI. You do this because your GUI users are very likely to print or plot, and the printer list is not likely to change while the user is using your GUI.
Odds are that the generatePrinterList() thread will finish long before your user has to print or plot. But just to be sure, the thread has to have a way of reporting back that the thread is completed. I use a boolean isCompleted that can be read with a public isCompleted() method.
The isCompleted() method could have a thread sleep loop if you want, so it always returns true. In this case the method doesn't have to return anything.