I use FTP raw commands to upload file to a FTP server, I start a new thread to send file via socket in my code. when the newly started thread finished sending file I want to output some message to console, how can I make sure the thread have finished it's work ?
here is my code:
TinyFTPClient ftp = new TinyFTPClient(host, port, user, pswd);
ftp.execute("TYPE A");
String pasvReturn = ftp.execute("PASV");
String pasvHost = TinyFTPClient.parseAddress(pasvReturn);
int pasvPort = TinyFTPClient.parsePort(pasvReturn);
new Thread(new FTPFileSender(pasvHost, pasvPort, fileToSend)).start();
how can I make sure the thread have finished it's work ?
You do call Thread.join() like this:
...
Thread t = new Thread(new FTPFileSender(pasvHost, pasvPort, fileToSend));
t.start();
// wait for t to finish
t.join();
Note however that Thread.join will block until the other thread has finished.
A better idea is perhaps to encapsulate the upload-thread in a UploadThread class which performs some callback when it's done. It could for instance implement an addUploadListener and notify all such listeners when the upload is complete. The main thread would then do something like this:
UploadThread ut = new UploadThread(...);
ut.addUploadListener(new UploadListener() {
public void uploadComplete() {
System.out.println("Upload completed.");
}
});
ut.start();
For what you are trying to do, I see at least three ways to accomplish:
you could just let the uploading thread itself print the logging message or
in some other thread, you can join the upload thread. Using this approach you could do some other work before calling join, otherwise there is no gain from doing it in a separate thread.
you can implement some kind of listener, so an uploading Thread informs all registered listeners about it's progress. This is the most flexible solution, but also the most complex.
Related
A simple setup for testing purpose: I am intentionally waiting on a DatagramPacket, which will never arrive as there is no counterpart socket answering. But it freezes the UI also it runs on a seperate Thread inside a LocalService.
It runs fine if the socket.receive(paket);...} is removed.
Here the run() which is inside BackgroundService extends Service {...class ClientSocketThread extends Thread{...run()...}...}
#Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
try {
String stringSend = "hello from ClientSocketThread";
buffer = stringSend.getBytes();
packet.setData(buffer); //on init its empty
socket.send(packet);
socket.receive(packet);
String received = new String(packet.getData(), 0, packet.getLength());
Log.e("BackgroundService ", "received "+received);
} catch (Exception e) {
Log.e("BackgroundService ", "ClientSocketThread");
Log.e("BackgroundService", e.toString());
}
}
Android Monitor says this
Link to the traces.txt. The interesting line probably is :
- waiting to lock <0x41ed80a8> (a java.net.DatagramSocket) held by tid=13 (Thread-4376)
ADDON I now added a socket.setSoTimeout(3000) and notice that the UI is not updating exactly 3seconds. Could someone please explaine why?
I previously assumed:
I assume the Thread-4376 is blocking the CPU as it forever waits
for a packet to come, because no socket.setSoTimeout(time) is set.
Consequently main can not access the CPU to update UI which trows
ANR. Is this right?
I guess this is wrong. I did create some kind of lock for the UI-thread and made him wait, but lets leave it to itself. I choose a different approach and considered:
do not extend thread but use a Runnable, the codefragment that implements the task, and throw it into a fresh thread:
Thread t1 = new Thread(new SocketRunnable(ints, sleep));
modifying the UI-thread policy as I did before is not preferable. In Android Network operations on UI-thread are disabled by default. As I needed the flag the code had some connection to the UI-thread, which I finally could remove, success.
I have programmed a structure that works like this:
Activity discoveryActivity - UI thread
↕ Calls through interface
Service discoveryService - Bound service running on UI thread
↕ Actions through Handler.post(↑) or functions (↓)
Runnable connectionThread - Socket networking
At some point the connectionThread needs a String to continue.
So I make a call with Handler.post(..) to the discoveryService which
notifies the discoveryActivity to show an AlertDialog
The user needs about 20 seconds to input the data and will confirm the input.
Problem 1: What will the thread do in the meantime?
Now I need to make my way down to the Thread again.
Getting to discoveryService is easy
Problem 2: How can I get the thread working again without restarting? The thread is in a complex loop with a few Sockets right now!
My first idea was to keep the thread running
// Inside run()
while(stringWrapper.get() == null) {
Thread.sleep(500);
}
// Outside run()
void setStr(String s) { stringWrapper.set(s); }
But that is inefficient
Then I read about wait() and notify()
I tried that on the thread itself and on the StringWrapper (A simple class that holds a reference to a String)
I am helpless right know and I think wait() and notify() are the right way to go?
Can you give me a hint where I should implement these and on which object they would be called?
TL;DR: I want to let a thread pause until it receives data
Not 100% sure what you're trying to accomplish, but you may be able to use a SettableFuture (from Google Guava library) to solve your issue.
private final SettableFuture<String> stringFuture = SettableFuture.create();
// Inside run()
// This will block your thread until stringFuture is set, or until the given timeout has expired.
final String string = stringFuture.get(1, TimeUnit.MINUTES);
// Outside run()
public void setStr(final String s) {
stringFuture.set(s);
}
So I have this in a method:
Runnable task = new PostLoadRunnable(tool, archive);
SwingUtilities.invokeLater(task);
But I want to make it so that the current method does not continue until the task thread has completed. I want to do something like join() but I can't work out how to do it. task.join() and Thread.task.join() doesn't work and Thread.currentThread().join() doesn't give me any options to join it to the thread that I want.
How do I stop the method until task is finished?
You can accomplish this using a CountDownLatch. In your PostLoadRunnable run method you can have the following code in the finally section.
public void run() {
try {
...
} finally {
latch.countDown();
}
}
CountDownLatch latch = CountDownLatch(1);
Runnable task = new PostLoadRunnable(tool, archive, latch);
SwingUtilities.invokeLater(task);
latch.await();
You don't want to do this at all. You state in comments that this code runs in the event dispatcher thread. You must not block this thread. Otherwise you will freeze the entire UI and the user will be most unhappy.
What you probably should do is disable the relevant parts of the UI until the task has completed. But without knowing your actual wider requirement it isn't possible to be sure.
How to kill the thread?
.....
How to restart them again in multi threading?
Since your post is tagged "Java," I have a good idea of what you are saying. Let's say you start a thread by doing:
Thread foo = new Thread(someRunnable);
foo.start();
Now that destroy and friends are deprecated, you need a way to kill the thread. Luckily for you, there has always been the concept of "interrupts." Simply change your runnable so that, on interrupt, it exits. Then call the thread's interrupt method.
foo.interrupt();
If you wrote your Runnable to handle this correctly, it will stop whatever it is doing and terminate.
Thread.stop() kills a thread, but you definitely don't want to do this (see the API documentation for an explanation why). Thread.interrupt() sends an asynchronous notification to a thread, so that it can shut itself gracefully.
For a comprehensive text on Java multithreading, I recommend B. Goetz, Java Concurrency in Practice, Addison-Wesley Professional.
The preferred way for a Thread to die is for the execution of the run method to go to completion:
Thread t = new Thread(new Runnable() {
public void run() {
// Do something...
// Thread will end gracefully here.
}
}
Once a thread gracefully dies in the example above, the Thread cannot be restarted. (Trying to call Thread.start on a thread that has already been started will cause an IllegalThreadStateException.)
In that case, one can make another instance of the thread and call start on that.
Probably a good place to get more information on threading would be Lesson: Concurrency from The Java Tutorials.
i wrap my worker threads up in their own class and use a terminated property to kill the thread proc loop.
sorry i dont have a java version to hand right now but you should get the idea from this
http://pastie.org/880516
using System.Threading;
namespace LoaderDemo
{
class ParserThread
{
private bool m_Terminated;
private AutoResetEvent m_Signal;
private string m_FilePath;
...
public ParserThread(AutoResetEvent signal, string filePath)
{
m_Signal = signal;
m_FilePath = filePath;
Thread thrd = new Thread(this.ThreadProc);
thrd.Start();
}
public bool Terminated {
set { m_Terminated = value; }
}
private Guid Parse(ref string s)
{
//parse the string s and return a populated Guid object
Guid g = new Guid();
// do stuff...
return g;
}
private void ThreadProc()
{
TextReader tr = null;
string line = null;
int lines = 0;
try
{
tr = new StreamReader(m_FilePath);
while ((line = tr.ReadLine()) != null)
{
if (m_Terminated) break;
Guid g = Parse(ref line);
m_GuidList.Add(g);
lines++;
}
m_Signal.Set(); //signal done
}
finally
{
tr.Close();
}
}
}
}
The best way to kill a thread is to set up a flag for the thread to watch. Program the thread to exit when it sees the flag is set to true. There's no way to restart a killed thread.
If you want to start, stop, restart threads at will, maybe using the Java 5 concurrency package would be a good idea. You can have an Executor that will do a bit of work, and when you need that bit of work to be done again, you can just re-schedule it to be done in the executor.
Regarding your first query on killing thread:
You can find more details about topic in below SE questions:
How to properly stop the Thread in Java?
How can I kill a thread? without using stop();
How to start/stop/restart a thread in Java?
Regarding your second query of re-starting thread, it's not possible in java.
You can find below details in documentation page
public void start()
Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread.
The result is that two threads are running concurrently: the current thread (which returns from the call to the start method) and the other thread (which executes its run method).
It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.
Instead of plain Threads, you can use advanced concurrent API for thread life cycle management. Have a look at this post for ExecutorService details :
How to properly use Java Executor?
in my class I have an inline thread in the constructor that loads objects from a remote site:
Thread readSite = new Thread(new Runnable() {
public void run() {
site.loadStuff();
}
});
readSite.start();
I want to display a 'loading' message until the thread is finished. So before the above code I show a loading message.
After the above code I show the screen in which I would like to continue.
The code looks like this:
showLoadingView(); //tells the user it is waiting
Thread readSite = new Thread(new Runnable() {
public void run() {
site.loadStuff();
}
});
readSite.start();
showStuffView(); //works with the data retrieved from the site instance
Now, the main thread of course continues and the showStuffView() is directly executed.
I can now let the main thread wait for the readSite Thread, but then the user cannot accept the connection request ('is it ok to use airtime?') that is shown to the user (because the responsible thread is asleep I guess).
On the other side, I cannot execute the showStuffView() from the readSite Thread.
I hope you guys can explain how to wait for this thread. I looked into synchronized, but couldn't really find a nice solution.
I think this is a common problem with threads and this particular problem you can solver with boolean variable. but for general purpose i think observer pattern is good.