I am using OpenCYC api (no too common, besides the point though), and I am trying to create an object AccessObject named ao. The problem is, for whatever reason, an AccessObject cannot be instantiated inside the main Java Swing Event Thread.
So as a workaround, I made another thread that just instantiates an AccessObject in it's run() method and also provides a getter for it to return it.
So this is what I have for the calling code:
// do something with code
AccessObject ao;
AccessObjectInstantiateThread aoThread = new AccessObjectInstantiationThread();
aoThread.start();
while(ao == null) // while loop to ensure we "wait" for aoThread to finish
{
ao = aoThread.getAoObject();
}
// Then use ao however you want
Now this code works, but it seems pretty rediculous. Is there any better way to do this? Remember, there is no way I can instantiate an AccessObject under the main java event thread.
Thank you very much, Rich.
Instantiate it in a SwingWorker object, and check for a valid object before completing the doInBackground() method.
Add a PropertyChangeWorker to the SwingWorker that listens for SwingWorker.StateValue.DONE, then pass the object to your Swing program.
For example,
class MySwingWorker extends SwingWorker<AccessObject, Void> {
public AccessObject doInBackground() throws Exception {
// do whatever needed to create your AccessObject and check its completion
// return your AccessObject
}
}
In your Swing code:
final MySwingWorker mySwingWorker = new MySwingWorker();
mySwingWorker.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChanged(PropertyChangeEvent pcEvt) {
if (pcEvt.getNewValue() == SwingWorker.StateValue.DONE) {
try {
ao = mySwingWorker.get(); // ao is an AccessObject class field
// you can use ao here
} catch (whaeverExceptionYouAreTrapping e) {
// do something with exception
}
}
}
});
mySwingWorker.execute();
Note, code note tested nor compiled.
Edit as per JB Nizet's recommendation you could also simply do an anonymous inner class in your Swing code and skip the PropertyChangeListener:
new SwingWorker<AccessObject, Void>() {
public AccessObject doInBackground() throws Exception {
// do whatever needed to create your AccessObject and check its completion
// return your AccessObject
}
public void done() {
try {
ao = mySwingWorker.get(); // ao is an AccessObject class field
// you can use ao here
} catch (whaeverExceptionYouAreTrapping e) {
// do something with exception
}
}
}.execute();
Your code may not work. You should at least declare your variable as follows:
volatile AccessObject ao;
The reason is, your EDT thread may cache the value of ao variable as an optimization and may not see ao is assigned to a new value.
I hope this code is at the beginning of you application and users will not see UI is not responding.
Ideally you would create AccessObject ao on the start up thread (in the main() method) and not start your UI (EventQueue.InvokeLater with a runnable containing something like new JFrame) until after you had.
Failing that, make ao volatile. Your instantiation code should set this value directly rather than bothering about a "get" method. It should probably also call InvokeLater with a runnable to readjust the display--maybe enable a button or two and send the user a message that things are now possible that were not possible before.
Any code accessing ao has to be prepared for the fact that it may be null; your GUI has to work both ways, making its situation clear to the user. Every check or reference should look something like:
final AccessObject local_ao = ao;
if (local_ao != null) {
// Do things. USE local_ao, NOT oa!!!
}
In short, always use local_ao, which won't change. Remember that the value of ao can and will change at any time. As you've described it, it will only change from null to non-null, and do so only once, but that may change as your code evolves. (If it won't evolve, my first suggestion might be best.)
Your UI (EventQueue) code should not wait for anything. Threads are pain, and I'd take a little delay in the UI over using a thread any day. But you've already paid the price for a thread, so you may as well get your money's worth.
Related
I'm trying to wait for a piece of code to return true before I proceed with everything else. I have two classes, each has one instance running.
Main where I open the new object I want to wait for to complete
setupWizard setup = new setupWizard();
setup.setVisible(true);
setup.setCallerRef(new java.lang.ref.WeakReference(this));
synchronized(this) {
while (setup.isItComplete() == false) {
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
ArrayList<String> accounts = Functions.fetchAccounts();
SetupWizard i want to wait for
public setupWizard() {
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
//get handlers
JButton helpBtn = (JButton)getContentPane().getComponent(9);
JButton saveBtn = (JButton)getContentPane().getComponent(8);
JTextField userName = (JTextField)getContentPane().getComponent(3);
JTextField serverField = (JTextField)getContentPane().getComponent(1);
JPasswordField passwordField = (JPasswordField)getContentPane().getComponent(5);
JScrollPane scrolly = (JScrollPane)getContentPane().getComponent(7);
JLabel customQLabel = (JLabel)getContentPane().getComponent(6);
scrolly.setVisible(false);
customQLabel.setVisible(false);
//theb change btn positions and action listeners
setBounds(100, 100, 435, 220);
changeHelpButton(helpBtn);
helpBtn.setEnabled(false);
changeSaveButton(saveBtn, userName, serverField, passwordField);
registerAccount("hi", "hi");
}
public void registerAccount(String pass1, String pass2) {
if (pass1.equals(pass2)) {
Functions.addToDatabase("admin", pass2, 1, 1, 1, 1);
}
setComplete(true);
synchronized(getCallerRef()) {
getCallerRef().notifyAll();
}
dispose();
}
private boolean complete = false;
private Object callerRef;
public boolean isItComplete() {
return this.complete;
}
public void setComplete(boolean variable) {
this.complete = variable;
}
public void setCallerRef(Object mycaller) {
this.callerRef = mycaller;
}
public Object getCallerRef() {
return this.callerRef;
}
As you can see this is only the relevant section of the code. However, what happens is the Main thread freezes, but the second UI that should pop up is just a see-through window with nothing on it. What might be the problem? Or is there any other viable approach to "block code until x becomes true"?
Edit:
Ok I think i figured out a problem with this; if i just initialise the class, and then immediately call registerAccount() from the initialiser method of the second class without trying to do anything with the UI, it works. However, I don't immediately want to go to registerAccount(), because before then there is a semi-long procedure the user has to go through to input all sorts of data, after which the main us has to be unfrozen. Any ideas?
I really can't tell for sure from the code you posted, but I suspect your situation might be that the SetupWizard is a Frame or Dialog and the code in Main is executed by EDT, so when you put EDT on wait in Main you are freezing your GUI and SetupWizard code cannot execute neither.
I suggest you just use a Modal Dialog for SetupWizard. It will block Main while SetupWizard is visible.
You are not using wait() correctly, but it could be very useful in doing what you'd like to do.
First, read the javadoc on Object.wait
Then, in your code where you are currently calling
this.wait()
change this to
synchronized (setup) {
setup.wait();
}
In setup, change setComplete to
public synchronized void setComplete(Boolean variable) {
this.complete = variable;
if (variable) {
this.notifyAll();
}
}
This is the basic framework (there's plenty built on top) of how you do efficient multithreaded locking / waiting / synchronizing
There are two different objects, the notifyAll you invoke is on the WeakReference object where as you wait on the object of Main.
In the registerAccount method of setupWizard class you need to do changes as below so that you notify on the same object as the object upon whose lock Main thread is waiting.
Object lock = ((WeakReference)getCallerRef()).get(); // this will be object of Main in case its not null.
if( lock != null){
synchronized( lock ) {
lock.notifyAll();
}
}
Edit One basic issue in the code you have is that you have justthe single thread. Same thread goes in wait and same thread tries to invoke notifyAll. If this thread goes in wait state then there is no thread which can invoke notifyAll , this results in application being in hanged state forever. You need to invoke the setupWizard constructor from a separate thread.
EDIT 2
there are many issues with your code.
You need to have separate thread calling the registerAccount so that notifying thread is different from the waiting thread.
Your constructor invokes currently the registerAccount which tries to synchronize on the lock objct but you pass the lock object from main after contructor is invoked.
your object on which you wait and on which you invoke notifyall are different objects
I would like to start off by saying that if you know a better way to do this, please tell me. I would rather know a better way of doing this than doing it incorrectly.
I am writing a server program that has to interact with multiple clients. I am using the method that this answer proposed. (socket programming multiple client to one server). I am creating the new Instance of the 'EchoThread'.
I also have another class that has a number of variables that need to be able to be accessed and changed by ALL the classes / operations in my server. I am wondering how I inject (I think that is what it's called) the Instance of that from the class creating the new 'EchoThread' object and the 'EchoThread' Class.
Part of the answer from the link above:
while (true) {
try {
socket = serverSocket.accept();
} catch (IOException e) {
System.out.println("I/O error: " + e);
}
// new threa for a client
new EchoThread(socket).start();
}
I have the Instance of the class I want to inject:
VarsClass vars = new VarsClass();
I normally "link" these by doing thing:
VarsClass vars = new VarsClass();
ExampleClass example = new ExampleClass();
example.link(vars);
Here is the 'link' method in the 'ExampleClass'
public void setGlobalVariables(GlobalVariables global) {
this.globalVariables = global;
}
How do I reference the 'EchoThread' like I do in the above example with 'ExmapleClass' and 'VarsClass'? I am doing this, so each class is not creating a new instance of the VarsClass. (Avoiding the problem I had here: Using the same variables in two threads, but I don't know why they won't update in Java)
Thank you to every one in advance for your patience and help.
~Rane
How do I reference the EchoThread ...
The simple way is like this:
EchoThread et = new EchoThread(socket);
et.link(vars);
et.start();
Or pass the vars object as another argument to the constructor.
Note that the following variant is wrong ... unless you make EchoThread thread-safe.
EchoThread et = new EchoThread(socket);
et.start();
...
et.link(vars);
(It is safe to pass the argument prior to the start() call because there is an explicit "happens before" on the start() call ... between the thread that calls start() and the starting of new thread's run() method.)
The other thing to note is that writing subclasses of Thread is generally considered to be a poor way of implementing multi-threading. A better way is to implement your thread's logic as a Runnable; e.g.
public class MyRunnable implements Runnable {
// thread state variables here ...
public MyRunnable(Socket sock, GlobalVariables vars) {
...
}
public void run() {
// thread logic goes here ...
}
}
and the use it like this:
new Thread(new MyRunnable(sock, vars)).start();
This approach allows you to easily change your code to use a thread pool or an Executor instead of a Thread that you create on the fly. (Creating threads on the fly tends to be expensive.)
You can do it the same way as with instances of any other class.
EchoThread thread = new EchoThread(socket);
thread.setGlobalVariables(globalVars);
thread.start();
I am using AsyncTask to run a background operation. Of course switching to another thread while already working in a background thread does not make a lot of sense in general, except the other thread is the UI thread. This what I would like to to: While the task is running I need to "access" the UI, e.g. to show a dialog to ask the user how to proceed.
run the background task
stop the task at some point to get user feedback
switch to the UI thread to show dialog and ask for input
switch back to background task and continue work
How can this be done? I thought I could use Runnable with myActivity.runOnUiThread(runnable) but this does not work:
private void copyFiles() {
CopyTask copyTask = new CopyTask(this);
copyTask.execute();
}
// CustomAsyncTask is a AsyncTask subclass that takes a reference to the current
// activity as parameter
private class CopyTask extends CustomAsyncTask<Void, Void, Void> {
private doCopy;
#Override
protected Boolean doInBackground(Void... params) {
// Custom code, e.g. copy files from A to B and check for conflict
for (File file : allFiles) {
doCopy = true;
if (isConflict(file)) {
// Stop current thread and ask for user feedback on UI Thread
Runnable uiRunnable = new Runnable() {
public void run() {
// Pos 1. --> Execute custom code, e.g. use AlertDialog to ask user if file should be replaced...
doCopy = false;
synchronized (this) {
this.notify();
}
}
});
synchronized(uiRunnable) {
// Execute code on UI thread
activity.runOnUiThread(uiRunnable);
// Wait until runnable finished
try {
uiRunnable.wait();
}
catch (InterruptedException e ) {
e.printStackTrace();
}
}
}
// Pos 2. --> Continue work
if (doCopy)
copyFromAToB(File);
}
return null;
}
}
Within doInBackground() (--> in a background thread) the AsyncTask calls activity.runOnUiThread(uiRunnable). Next uiRunnable.wait() is called. Regarding to the docu wait() should do the following:
Causes the calling thread to wait until another thread calls the
notify() or notifyAll() method of this object.
Thus the background thread should wait to continue its work until this.notify() (== uiRunnable.notifiy()) is called on another thread (= the UI thread), shouldn't it?
Well, id does not wait! After calling uiRunnable.wait() the background thread immediately continues by jumping to if (doCopy).... It seems that the background thread and the main thread are executed in parallel (not surprising since this is what thread do...) and thus its a race condition whether doCopy = false on the UI thread or if (doCopy) on the background thread is reached first.
How is this possible? Why doesn't wait() works as described? Or am I getting something wrong?
Thank you very much!
EDIT:
To avoid missunderstandings: Of course I know the lifecycle methodes of AsyncTask but as far as I understand them, they are not what I am looking for (see my reply to the comment blow).
Interrupting the AsyncTask as soon as a UI interaction is necessary, query the UI and start a new AsyncTask would be possible of course. However this would result in code which is very hard to read/understand/maintain.
As I understand the docu of wait() everything should work fine here. Primary question is not how to do UI interaction during the lifecycle of an AsyncTask but why wait()does not work as expected.
The Basics
When you start an AsyncTask first the onPreExecute() method runs on the UI thread. You can override this method to make changes to the UI prior to the doInBackground() method running.
After the doInBackground() method finishes, the onPostExecute() method runs on the UI thread, so you can use this to make changes to the UI from here. If you need to make regular changes to the UI Thread during the doInBackground() method you override the onProgressUpdate() method which runs on the UI Thread, and then call it from within doInBackground(), which will allow you to periodically update the UI.
You could use something like the following;
private class DoStuffTask extends AsyncTask {
#Override
protected void doInBackground(Object... args) {
// Do stuff
onProgressUpdate(x);
// Do more stuff
}
#Override
protected void onProgressUpdate(Object... args) {
// Update your UI here
}
}
Now if this doesn't quite do it and you want the AsyncTask to wait for input during the doInBackground() method it is probably worth considering using multiple AsyncTasks instead. You can then finish each AsyncTask, ask for input, and then start a new AsyncTask to continue working.
Given that AlertDialog instances are asynchronous, this is probably the preferred solution because you can start the next AsyncTask from the AlertDialog itself.
Using wait() in an AsyncTask
If you would prefer to use a single AsyncTask you can use wait from within your AsyncTask to prevent execution continuing until some condition is met. Instead of using a new Runnable we are just using two threads in this instance, the thread running doInBackground() and the main thread, and we are synchronizing on the AsycTask itself.
Example below;
public class TestTask extends AsyncTask{
private boolean notified;
private Promptable p;
public interface Promptable { public abstract void prompt(); }
public TestTask(Promptable p){
this.p = p;
}
#Override
protected Object doInBackground(Object... arg0) {
Log.d("First", "First");
onProgressUpdate(null);
synchronized(this){
while(!notified){
try{
this.wait();
}
catch(InterruptedException e){ }
}
}
Log.d("Second", "Second");
return null;
}
#Override
protected void onProgressUpdate(Object... args){
synchronized(this){
notified = true;
p.prompt();
this.notify();
}
}
}
In the example above, assume that your Activity is parsed into the AsyncTask's constructor, and that it implements an interface we create called Promptable. You'll notice that even though we're calling wait() we are putting it in a while loop. If we didn't do this, and somehow notify() got called before wait() then your thread would lock up indefinitely. Also, you can't depend on the fact that your thread will wait forever, so the while loop ensures that it doesn't continue until notify is called.
I hope this helps.
So I have a somewhat general question regarding something I came across recently. Let's say have I have 2 classes, Activity and Task. In Activity, a new Task object is instantiated, but instead of being given its usual parameters, some new code is introduced in brackets afterward, and one of its methods is called on that instantiation. I've seen methods being called on an object as soon as it is created, but not re-defining its behavior also. This is all Android based, so maybe it's related to that, but something this syntactically weird seems more like a Java concept than something that Android introduced. Here's the class file:
class Task extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... args) {
try {
//do things here
} catch (Exception ex) {
ex.printStackTrace();
Log.e("Exception", ex.toString());
}
return Text;
}
}
which is the object to be created, and then the code which instantiates it is here:
new Task() {
#Override
public void onPostExecute(String result) {
Log.d("JSON", result);
try {
if (jObject.has("error")) {
//Do something here
}
else if (!paymentCheck(appDomain)){
//do something else
}
else {
//Do last thing
}
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
}.execute(appDomain, email, password);
I understand that AsyncTask is a quirky class in that it passes the result from its doInBackground method to the onPostExecute one in a separate thread, and maybe that's why this is done, but I dont really understand why you wouldn't just define onPostExecute in Tasks own class file, like I've seen with other examples. Also, this thing compiles and runs perfectly fine, doing everything it's supposed to to. I just don't really understand the reasoning behind. Hopefully someone here can help! Thanks
This is a Java syntactic sugar called an anonymous class.
I'm not an Android developer so I'm not entirely familiar with any peculiarities there, but this pattern is used whenever you need to ensure that the response action occurs in a separate thread to avoid deadlocks and the like or when the onPostExecute manipulates objects that are not visible in Task. This can act as a sort of closure over any final objects that are in scope.
I have an Android app with a main tab activity, and several activities within the individual tabs. In my main activity's onCreate(), I have a runnable that creates a list, and in the individual activities, I make use of this list.
In the individual activities's onCreate(), I also have Runnables that operate on the list. However, I need these Runnables to only run when the main tab activity's Runnable completes creating the list, otherwise I'd get a null list. I'm trying to find an elegant way of doing this. Right now, in my main activity's Runnable, I'm setting a global boolean variable isDone, and in my individual activity's Runnable, I'm waiting for isDone to be set via a while loop. This works, but probably isn't the best way of doing so.
Any thoughts?
Thanks.
Edit:
I'm trying the following code out, but I'm getting runtime errors:
In my MainActivity's Runnable:
mainRunnable = new Runnable() {
public void run() {
try {
generateList();
synchronized(this) {
listDone = true;
notifyAll();
}
} catch (Exception e) {
Log.e("BACKGROUND_PROC", e.getMessage());
}
}
};
Thread thread = new Thread(null, mainRunnable, "Background");
thread.start();
In my OtherActivity's Runnable:
otherRunnable = new Runnable() {
public void run() {
synchronized(MainActivity.mainRunnable) {
if (!MainActivity.getListDone()) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
}
};
Thread thread = new Thread(null, otherRunnable, "Background");
thread.start();
The mainRunnable seems to run completely, but the otherRunnable seems to cause the app to crash. I get the following error message:
01-10 15:41:25.543: E/WindowManager(7074): Activity com.myapp.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView#40539850 that was originally added here
01-10 15:41:25.543: E/WindowManager(7074): android.view.WindowLeaked: Activity com.myapp.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView#40539850 that was originally added here
You can use the wait and notify methods.
To do this, there needs to be some globally accessible object whose lock isn't used by anything else in the program at this point in time. I'm assuming that the list-creating Runnable itself can play this role.
So you could add something like this to the list-creating Runnable class:
private boolean listsDone = false;
boolean getListsDone() {
return listsDone;
}
And something like this to its run() method, immediately after it's done creating the lists:
synchronized (this) {
listsDone = true;
notifyAll();
}
And something like this to the other Runnables' run() methods, at the point where they need to wait:
synchronized (listCreatingRunnableObject) {
if (!listCreatingRunnableObject.getListsDone()) {
try {
listCreatingRunnableObject.wait();
} catch (InterruptedException e) {
// handle it somehow
}
}
}
Update: To clarify, both synchronized blocks need to be synchronized over the same object, and you have to call wait() and notifyAll() on that object. If the object is the Runnable, then it can be implicit for the first one (as in the above code), but if it's the activity, you need to explicitly use the activity object in both cases.
You can use a Queue like this:
public class RunQueue implemements Runnable
{
private List<Runnable> list = new ArrayList<Runnable>();
public void queue(Runnable task)
{
list.add(task);
}
public void run()
{
while(list.size() > 0)
{
Runnable task = list.get(0);
list.remove(0);
task.run();
}
}
}
This allows you to use one thread rather than multiple threads. And you can maintain all your existing "Runnable" objects while simultaneously cleaning up any code they have for waits and joins.
Set up a CountDownLatch with a value of 1 in the main thread, then have the dependent threads wait on it. When the main thread is done, you Count Down the latch to 0 and the waiters will start right up.
An active wait using a while loop is not a good idea at all. The simplest thing would be for the first Runnable to just fire up the rest of them as its last step. If that can't be made to work for some reason, take a look at posting a message to a Handler.
Is there a reason you are using Runnables and not Threads? If you use Threads, you can use the various thread communication primitives which exist for this exact reason (wait() and join() in particular).
I have created a helper method that contains all the boilerplate code for posting a runnable and waiting until it finishes running.
The logic is similar to what #Taymon describes, but the implementation is more general.
Check it out:
https://gist.github.com/Petrakeas/ce745536d8cbae0f0761
Maybe you can refer to Looper in Android. Simply, a thead keep running task from queue in a while loop.