I have this code:
public class JsoupParser {
ArrayList<CompanyInfo> arr = new ArrayList<CompanyInfo>();
public JsoupParser() {}
public ArrayList<CompanyInfo> parse(final String link) throws IOException {
Runnable runnable = new Runnable() {
public void run() {
// Here I do some operations and then assign some value
// to my `arr` ArrayList
}
};
new Thread(runnable).start();
return arr; // error here, as expected
}
}
System immediately returns arr, which at that point is null.
How can I return arr only after Thread finishes? How can I be informed, that Thread has finished?
How can I return arr only after Thread finishes? How can I be
informed, that Thread has finished?
Thread parseThread = new Thread(runnable).start();
parseThread.join();
return arr;
There's the literal answer to your question but zmbq's answer is more fitting for what you're after.
The whole point of using another thread, is to have it run while your main thread does something else. If you want your parse method to return the array when it's done, it shouldn't start another thread.
However, since I suppose you do want the calculation to take place in the background, you need to do something else. Why don't you take a look at AsyncTask? It is probably what you need.
Related
I'm working on some sensitive LWJGL code and need to make sure that I create my display, and therefore GL context before executing any other code.
To give a clear example of my current predicament, take the following:
public static void main(String[] args) {
GLDisplay display = new GLDisplay();
display.start();
GLShader shader = new StaticShader();
}
The beginning of my GL creation happens in display.start(), where a separate thread is created, and within the separate thread, my Display is created.
Except this is where the problem lies, I have it in a separate thread. So then my program goes on and starts prematurely executing the new StaticShader() which calls even more GL code, breaking the program. (Can't execute before display is created).
What I'm trying to do, is achieve two threads simultaneously which I already have, but make sure that start() method is called completely before anything else is.
Here is how the start method works:
public synchronized void start() {
Threader.createThread(this, "GLDisplay");
}
#Override // public class GLDisplay extends Runnable
public void run() {
// GL code goes here.
}
And here is Threader:
public static void createThread(Runnable behaviour, String name) {
new Thread(behaviour, name + behaviour.hashCode()).start();
}
Now you may notice the synchronized keyword in the start method, well thats just one attempt I've had to no avail. I've also tried the following (which I actually grabbed from another StackOverflow answer):
#Override
public void run() {
synchronized(this) {
// GL code
}
}
I've checked other StackOverflow answers but either don't understand them or don't help me in my case. With the first code block I give in the main method, that is how I want my code to look to the person using it. I'm trying to put the thread-creation inside GlDisplay to hide it.
Any ideas?
Edit:
I can't simply wait for GLDisplay to close either (with Thread.join()) because there lies a while-loop that updates the display for the entirety of the program.
This is the entire reason I multi-threaded it. To allow this forever-ending loop to run while I do other things in the program. By closing the thread, I close the loop, cleanup the display and free the GL context from memory, once again making the shader code fail for lack of an existing context.
You can use java.util.concurrent.CountDownLatch to achieve it which aids in making a thread(s) wait till the operations on other threads is complete. Please see the reference on on what and how to use it.
Example:
public static void main(String[] args) {
CountDownLatch cdl = new CountDownLatch(1);
// pass the CountDownLatch into display
GLDisplay display = new GLDisplay(cdl);
display.start();
// wait for the latch to have been counted down in the disp thread
try
{
cdl.await();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
GLShader shader = new StaticShader();
}
In your GLDisplay thread, call the countDown method of CountDownLatch
I might be misunderstanding something, but try the following:
public static void createThread(Runnable behaviour, String name) {
Thread t = new Thread(behaviour, name + behaviour.hashCode()).start();
t.join();
}
By calling join() the program should wait for the thread to complete.
Well I remember now that I can't have GL code against two separate threads anyway, but thats besides the point.
I don't actually need to use any thread-lock classes or anything, but rather can just do something as simple as this:
private Boolean threadLock = true;
public void start() {
Threader.createThread(this, "GLDisplay");
while (true) {
synchronized(threadLock) {
if (!threadLock) break;
}
}
}
#Runnable
public void run() {
// Do GL code.
synchronized(threadLock) { threadLock = false; }
// Do the rest of whatever I'm doing.
}
When the threadlock is reached in the second thread and is released, the first thread continues doing it's activity. It's that simple!
I am trying to perform a replace operation on the same string with multiple threads. I have created a class that will do so, given the text and a list of string arrays containing the targets and replacements:
public class ParallelReplacer implements Runnable {
private String text = "";
private List<String[]> targetsAndReplacements = null;
public ParallelReplacer(String text, List<String[]> targetsAndReplacements) {
this.text = text;
this.targetsAndReplacements = targetsAndReplacements;
run();
}
public void run() {
for(String[] s : this.targetsAndReplacements) {
this.text = performReplace(text, s);
}
}
private String performReplace(String text, String[] targetAndReplacement) {
text = text.replace(targetAndReplacement[0], targetAndReplacement[1]);
return text;
}
}
I execute it like so:
List<String[]> targetsAndReplacements = new ArrayList<String[]>();
targetsAndReplacements.add(new String[] {"a", ""});
targetsAndReplacements.add(new String[] {"e", ""});
targetsAndReplacements.add(new String[] {"i", ""});
targetsAndReplacements.add(new String[] {"o", ""});
targetsAndReplacements.add(new String[] {"u", ""});
String text = "I am trying to perform a replace operation the same string with multiple threads.";
text = new ParallelReplacer(text, targetsAndReplacements.subList(0, targetsAndReplacements.size() / 2)).getResults();
text = new ParallelReplacer(text, targetsAndReplacements.subList(targetsAndReplacements.size() / 2, targetsAndReplacements.size())).getResults();
However, the second thread only executes after the first thread has finished, defeating the purpose of haveing multiple threads. How can I have the two threads executing simultaneously, and then merge the results after they are done?
All your program is in the same thread
A Runnable it's a interface that need to be passed as argument of a thread
You need to execute the ParallelReplacer's instances in new threads
The question that maybe you gonna have, is how get the result, so, you want to use a callback to this, when the execution of the thread is done, the callback is called
public interface IMyCallback {
public void onSucess(String result);
public void onError();
}
Do this in ParallelReplacer
public class ParallelReplacer implements Runnable {
//...
IMyCallback myCallback;
public ParallelReplacer(String text, List<String[]> targetsAndReplacements, IMyCallback myCallback)
{
this.myCallback = myCallback;
this.text = text;
this.targetsAndReplacements = targetsAndReplacements;
run();
}
public void run() {
for(String[] s : this.targetsAndReplacements) {
this.text = performReplace(text, s);
}
myCallback.sucess(text);
}
}
Declare this out of the next method:
int finishedThreads = 0;
ArrayList<String> resultsThreads = new ArrayList<String>();
Do this:
public void callMeWhenAThreadFinished(String result){
finishedThreads++;
resultsThreads.add(result);
if(finishedThreads==2){
//do what you want to do with the results
}
}
and this:
//...
Runnable r1 = new ParallelReplacer(someText, targetsAndReplacements.subList(0, targetsAndReplacements.size() / 2),new IMyCallback() {
#Override
public void onSucess(String result) {
callMeWhenAThreadFinished(result);
}
#Override
public void onError() {
}
});
new Thread(r1).start(); //You forgot this
Runnable r2 = new ParallelReplacer(someText, targetsAndReplacements.subList(targetsAndReplacements.size() / 2, targetsAndReplacements.size()),new IMyCallback() {
#Override
public void onSucess(String result) {
callMeWhenAThreadFinished(result);
}
#Override
public void onError() {
}
});
new Thread(r2).start();
Hugs
While this may be helpful for starting to learn about multithreading, it's not useful for string processing. As stated in the comments, it's not gonna be conducive to merging the string later (at least in its current form).
The answer to your question is that Runnable provides a way to run functionality in a separate thread. But it doesn't provide the background thread itself.
In order to have it work in separate threads, you'd need to do something like this:
Thread first = new Thread(new ParallelReplacer(text, tars.subList(0, tars.size() / 2)));
Thread second = new Thread(new ParallelReplacer(text, tars.subList(tars.size() / 2, tars.size())));
Then you need to use the Thread.join API to wait for completion of the background threads in order to get the results. Or Object.notify in the threaded code, with Object.wait in the code that needs it.
I'm guessing that this is a homework question, so I won't go further here. But please do note that writing multithreaded code is nontrivial, and hard to get right even for very experienced developers. If this isn't just homework, you'll do far better using a proven library to help accomplish your work.
the fundamental problem with your code is that it never uses any threads.
a Runnable in java is just a class that's garunteed to have a void method run that takes no arguments, so you're just calling it as you would any other function
Starting the Threads
to use threading, java has it's own class, Thread,
where thread is expecting a class that implements runnable, so you can do
ParallelReplacer[] replacers=new ParallelReplacer[{number of threads}];
Thread[] threads=new Thread[{number of threads}];
for(int i=0;i<threads.length;i++){
replacers[i]=new ParallelReplacer(...);
threads[i]=new Thread(replacers[i]);
}
this makes an array of Thread objects, ready to go with the replacer they're supposed to run, but it doesn't start them yet. To spawn the thread you call .start() on that thread, beginning it's execution, separately from the main thread, which continues running.
so you would do
for(int i=0;i<threads.length;i++){
thread[i].start();
}
or just start each one after you create it in the previous loop
Output
the main thread of execution runs separately, and will run the next couple of commands before the ones you spawned finish execution, (even if the next command is return!), so you need to at some point tell your main to wait for all the spawned threads to finish
you can do this by calling join() on each spawned thread
for(int i=0;i<threads.length;i++){
threads[i].join();
}
what join does is it tells the currently executing thread (ie main in this case) to wait until the thread it's called on to finish. because of this, it has to be done in a separate loop, other wise you would just have
start thread 1,
stop thread 1
start thread 2
...
and might as well not use threads at all
after all the threads are joined, you can loop through the replacers array, and append all the results.
however
you can do better! all the threads share the same heap, which is where java allocates it's objects. if you change your input string (which is immutable) to a StringBuilder (which can be changed in place), then you could have each thread change it's section, and when they are all joined, the StringBuilder would be all replaced.
I've a method who return a result (return an integer), my method is executed in a Thread for load 40 000 objects, i return an integer who count the number objects loaded. My question is, How return the int with the Thread ? Actually, the result is returned directly and is equal to 0.
public int ajouter(params) throws DaoException, ConnectException {
final ProgressDialog dialog = ProgressDialog.show(mActivity, "Title",
"Message", true);
final Handler handler = new Handler() {
public void handleMessage(Message msg) {
dialog.dismiss();
}
};
Thread t = new Thread() {
public void run() {
try {
Str_Requete = "SELECT * FROM Mytable";
ResultSet result = ExecuteQuery(Str_Base, Str_Requete);
Index = addObjects(result);
handler.sendEmptyMessage(0);
} catch (SQLException e) {
e.printStackTrace();
}
}
};
t.start();
return Index;
}
When i call my method in my mainActivity :
int test = myObjs.ajouter(params);
test is equal to 0, the value is returned directly...
My constraint is didnt use AsyncTask.
The whole point of using a Thread is not to block the calling code while performing the task of the thread. Thread.start() returns immediately, but in the meantime a new thread is started in parallel to the current thread which will execute the code in the run() method.
So by definition there is no such thing as returning a value from a thread execution. You have to somehow send a signal back from the thread that performed the task to the thread in which you need the result. There are many ways of doing this, there's the standard Java wait/notify methods, there is the Java concurrency library etc.
Since this is Android, and I assume your calling code is running on the main thread, it's probably wise to use the functionality of Handler. And in fact, you are already doing that - you have a Handler that closes the dialog when the thread is done with its work - but for some reason you seem to expect the result of that work to be ready before it has even started. It would be reasonable to extend your existing Handler with some code that does something with the calculated value and remove the code that returns the value of a variable before or at the same time as it's being calculated by another thread.
I also strongly encourage you to study some concurrency tutorial such as Oracle's concurrency lesson or Android Thread guidelines to really understand what's going on in the background. Writing concurrent code without mastering the concepts is bound to fail sooner or later, because it's in the nature of concurrency that multiple things are happening at the same time, will finish in random order etc. It may not fail often, but you will go crazy wondering why something that works 90% of the time suddenly fails. That's why topics such as atomicity, thread synchronization etc are critical to comprehend.
Edit: Simple Android example of starting a worker thread, performing some work, posting back event to main thread.
public class MyActivity extends Activity {
private Handler mHandler = new Handler();
...
private void doSomeWorkInBackground() {
new Thread() {
public void run() {
// do slow work, this may be blocking
mHandler.post(new Runnable() {
public void run() {
// this code will run on main thread,
// updating your UI or whatever you need.
// Hence, code here must NOT be blocking.
}
});
}
}.start();
// This code will be executed immediately on the main thread, and main thread will not be blocked
}
You could in this example also use Activity.runOnUiThread(Runnable).
Please consider however that AsyncTask basically wraps this kind of functionality in a very convenient way, so if it suits your purposes you should consider using AsyncTask.
If you dont want to use AsyncTask or ForkJoin, then you could implement an Interface e.g. callback in your main class.
In your Example you dont wait until the Thread is done... thread.join
One Solution:
Your Thread is a extra class with an constructor to hold the reference to the calling class.
public Interface callback
{
public int done();
}
public class main implements callback
{
...
CustomThread t = new CustomThread(this)
...
}
public class CustomThread extends Thread
{
private Callback cb;
public CustomThread(Callback cb)
{
this.cb=cb;
}
.
.
.
//when done
cb.done(int)
}
I have a Singleton in an Android App (which works just fine) in one of the functions I need to set data in a class variable in another thread but the data only sets if I run the function twice.
onCreate:
Thread thread;
Runnable runnables;
String recvData;
#Override
public void onCreate() {
super.onCreate();
singleInstance = this;
recvData = "one";
Log.v("oncreate", "singleton");
}
threaded_data_set:
public String threaded_set_data() {
runnables = new Runnable(){
#Override
public void run() {
recvData = "two";
return;
}
};
thread = new Thread(runnables);
thread.start()
Log.v("Data", recvData);
return recvData;
}
on the first run it logs ("Data", "one") and only on the second one it changes to ("Data", "two")
What am I doing wrong here?
The default values of recvData is:
recvData = "one";
nothing is wrong here, the
Log.v("Data", recvData);
just printed out before your thread prints out the second log message.
You are assuming the thread has finished as soon as you get to the logging statement.
Try logging the value in the thread as you set it as well, you'll see that code happens after your first logging call.
It is working right but you're expecting the thread to finish before your method moves on is all :)
Not much is going wrong here, you just aren't using the new assignment value for recvData
public String threaded_set_data()
{
runnables = new Runnable(){
#Override
public void run() {
recvData = "two";
Log.v("Data", recvData);
//return; <-- not really needed
}
};
thread = new Thread(runnables);
thread.start()
Log.v("Data", recvData);
return recvData;
}
At the first run of the thread, the latter is running in it's own thread which means that you're already returning recvData before the runnable finishes running since it's running in parallel. What you would want to do is use an AsyncTask instead.
You're seem to missing the nuances of how threads work. I think you are assuming that your threads runs and returns before your log statement, however you can't safely assume that.
Instead, try using a handler like the comment in your question. A handler is designed exactly for this type of thing. Vogella (a fantastic resource btw) does a much better job of explaining it so I will direct you there.
I Want to execute a Certain Task to take only 1000 MS , if it exceeds , i dont want to continue with the task ,
i have used join for this .
Please tell me and guide me if this is correct or not
import java.util.List;
public class MainThread {
public static void main(String args[]) throws InterruptedException {
Thread mainthread = Thread.currentThread();
ChildThread child = new ChildThread();
Thread childThread = new Thread(child);
childThread.start();
mainthread.join(1000);
List list = child.getData();
if(list.size()<0)
{
System.out.println("No Data Found");
}
}
}
ChildTHread
import java.util.ArrayList;
import java.util.List;
public class ChildThread implements Runnable
{
List list = new ArrayList();
public List getData() {
return list;
}
public void run() {
// This List Data is feteched from Database currently i used some static data
list.add("one");
list.add("one2");
list.add("one3");
}
}
Nope. Incorrect. You do not need MainThread at all, you should call childThread.join(1000) instead.
But there is a problem with this approach as well - it will mean that the child thread will anyhow continue to be running.
Therefore you should call also childThread.interrupt() after join:
childThread.join(1000);
childThread.interrupt();
and in your child thread periodically in your childThread perform something like that:
if (interrupted()) {
return;
}
and handle InterruptedException where needed - usually around any wait() methods you have.
Interrupting a thread is the more common (and better) approach. If you want the task to execute for at most 1 second and then stop, use Thread.interrupt(), otherwise the thread will continue to run. It is important to note that depending on how your actual code is structured, you may need to propagate the interrupt.
EXAMPLE
public class Demo {
public static void main(String[] args){
final List<String> list = new ArrayList<String>(3);
final Thread t = new Thread(new Runnable(){
#Override
public void run() {
synchronized(list){
list.add("one");
list.add("one2");
list.add("one3");
}
}
}, "DemoThread");
t.start();
try {
t.join(1000);
t.interrupt();
} catch (InterruptedException e) {
// handle exception
}
synchronized(list){
if(list.isEmpty()){
System.out.println("No data found");
}else{
System.out.println(list);
}
}
}
}
No, this will not work, because this code will wait for one second, and if the thread is not finished, it will just go on. The thread will continue to run. Call thread.interrupt() to interrupt the thread, or close the connection so that it throws an exception and stops the thread, and then join on the thread.
yup that's the way, the only problem i see is in ChildThread list, i suggest you to use synchronized method like this so that you won't have race conditions
List list = Collections.synchronizedList(new ArrayList());
also if you want the running thread to be stoped if it's execution time exceeded 1000 ms i suggest you to use interrupt method of Thread object and don't forget to catch interrupt exception in child thread so you won't have unnecessary exceptions in log