Let thread wait for dialog input - java

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);
}

Related

Can a Thread in an ExecutorService call a method on a seperate thread?

I have a socket server that uses an ExecutorService to create a new thread for each new socket. I also have a static instance of a class that makes database calls that all threads use.
My server is used for online chess matches. When a user makes a move, the move is sent to the server and an entry is made in the DB with general information about the move (including the ID of the match). Every 10 seconds or so, if the match's other client also has an active socket to the server, it will ask the server to fetch all new data about the match.
It works, but as you can imagine gets pretty inefficient if a non-trivial number of players are connected. What I want is a way for a thread to peek into the thread pool and find another thread based off an ID (The ID of the client for whom the thread is used), then call a method on that thread to send a message to the opposing player.
I've been looking all over, and I've had no luck. Is such a thing possible? If it is, is it advisable? Even if it's a bit risky code-wise, I'm willing to take extra steps to mitigate the risk for the enormous resource-saving benefits.
Like I said in my comment, your question is confusing; if all you're trying to do is to notify the opponent when a player makes a move, the simplest implementation is to use a BlockingQueue. The Javadoc even has code examples, so it should be fairly easy to implement. In your case, whenever a player makes a move, you put an item in the queue, that the consumer picks up and notifies the opponent that is participating in the same game. You don't need to mess with low level thread constructs, and if you're even thinking of finding threads based on ids from a pool, you're doing it all wrong.
The BlockingQueue would work, but it involves busy wait, so I'm not a big fan of it. Instead, you can use the Observer design pattern; the JDK already has support for this. Following is an example that I made up:
public class Main extends Observable implements Observer {
private final int numCores = Runtime.getRuntime().availableProcessors();
private final ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(numCores);
public Main() {
addObserver(this);
}
public static void main(String[] args) throws InterruptedException {
new Main().execute();
}
private void execute() {
for (int i = 0; i < 5; ++i) {
this.setChanged();
this.notifyObservers(i);
try {
Thread.sleep(1000l);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
executor.shutdown();
}
#Override
public void update(Observable o, Object arg) {
System.out.printf("Received notification on thread: %s.\n", Thread.currentThread().getName());
executor.submit(() -> System.out.printf("Running in thread: %s, result: %s.\n",
Thread.currentThread().getName(), arg));
}
}
Received notification on thread: main.
Running in thread: pool-1-thread-1, result: 0.
Received notification on thread: main.
Running in thread: pool-1-thread-2, result: 1.
Received notification on thread: main.
Running in thread: pool-1-thread-3, result: 2.
Received notification on thread: main.
Running in thread: pool-1-thread-4, result: 3.
Received notification on thread: main.
Running in thread: pool-1-thread-5, result: 4.
Last but not the least, if you really want to take it up a notch, use messaging. You didn't mention if you're using a framework (again, lack of information on your part), but Spring supports messaging, so does Akka, Play and Camel.
You may create the ExecutorService supplying your own ThreadFactory able to create your istantiate your own class that extends Thread and has a reference to the ThreadFactory itself. The ThreadFactory should trak all created Thread and be able to identify them by their ID. Such a way, each Thread will be able to query the ThreadFactory for some ID.

Background processing java

Pardon my ignorance if this is a basic question.
I want to understand how can I return control from a module and start processing in background?
Lets start component A calls component B. Component B does some basic processing, starts a background thread and immediately returns control to A. Whenever background thread completes its processing it is going to store the result in a persistence store. Whole processing by this background thread is time consuming and A cannot wait until background thread finishes off.
Component A {
Http Call component B
}
Component B {
// Got request from component A
start background thread();
return; // don't wait till background thread finishes off
}
background thread() {
// time consuming task
}
How can I achieve this behavior in java? I don't think it is entirely asynchronous form of processing since communication is happening over http connection that has timeout settings.
Update:
Component A:
Receives Http call
Component B:
Approach1:
Runnable runnable = new MyThread();
new Thread(runnable).start();
Approach2:
ExecutorService exec = Executors.newSingleThreadExecutor();
exec.execute(new MyThread());
exec.shutdown();
Both of the above mentioned approaches helped me to start background processing and return immediate control to A.
Use threads at a raw level is good solution for some easy proof of concepts, but I strongly suggest at least try to use the concurrent API from java, you can find the documentation here. and a good tutorial is here
The simplest approach is to create a Callable object that contains the instruction you want to execute in background.
Callable myInstructions = new Callable<ObjectToReturn>() {
public ObjectToReturncall() {
return object.methodCall();
}}
Using the ExecutorService submit this callable to expect a Future object.
Future<ObjectToReturn> future = executor.submit(myInstructions);
//Do anything else as this wont be blocked ..
Future API have a set of method to ask if the task is already completed.
if(future.isDone()) // Ask if the task is done
ObjectToReturn solution = future.get() // Get the result
Very simple to use the Future API .
EDIT
If you dont expect any response from the Future api, just do an operation you could use
Future<Void> future = executor.submit(new Callable<Void>() {
public Void call() throws Exception {
testA.abc();
return null;
}
});
Other option if you dont want to receive a result or get a response, just fire a thread will be
ExecutorService executor = Executors.newFixedThreadPool(5);`
executor.execute(new RunnableClass());
Also avoid call shutdown on ExecutorService , do that just until the end of the process, when you dont have more time to do, in spring or container fwks the container is in charge of shutdown the ExecutorService once the app has been shutdown
The easiest way would probably be to create a new java Thread with the background processing logic as parameter.
void componentB() {
new Thread(new Runnable() {
#Override
public void run() {
// Time consuming task.
}
}).start();
// The method continues without stopping.
}
In later versions of java, you can also use the ForkJoinPool-class to achieve this:
public class Main {
private final ExecutorService executor = new ForkJoinPool();
void componentA() {
componentB();
}
void componentB() {
executor.execute(this::timeConsumingTask);
// The method continues without stopping.
}
private void timeConsumingTask() {
// Time consuming task.
}
}
Assuming you want the HTTP call to return before the background processing is complete, your pseudocode is perfectly valid for Java.
At the next level of detail, check out the Javadoc for Thread, Runnable, and the java.nio library classes.

When a thread is done, how to notify the main thread?

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.

About multi threading

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?

Use Threads in Midlet: how to listen to running thread?

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.

Categories

Resources