I'm trying to run a long-running process in Google App Engine using Java. (basically i need something like a daemon thread? or just something runs indefinitely and doesn't block UI but can still communicate with other threads)
so i tried:
#SuppressWarnings("serial")
public class TestingAServlet extends HttpServlet {
public void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws IOException {
resp.setContentType("text/plain");
new Thread(new Runnable() {
#Override
public void run() {
try {
resp.getWriter().println("hi, from background thread");
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
System.out.println("done");
}
}
but i get an exception:
java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "modifyThreadGroup")
how do i make a background thread that runs indefinitely on GAE with java?
AppEngine doesn't allow usage of traditional threads.
You can, however, use the Modules API to spawn background tasks:
https://developers.google.com/appengine/docs/java/modules/#Java_Background_threads
https://developers.google.com/appengine/docs/java/javadoc/com/google/appengine/api/ThreadManager
Note that such background tasks can only be spawned on manual scaling instances.
Related
I'd like to check to see if a Thread is Interrupted, from some other Thread, without polling this to check - i.e. some kind of monitor.
Specifically, what I am trying to do is force-kill (Stop) a Thread when it is Interrupted. I will include a code example below of a trivial example of what I have done so far - it works, but polling to check if the Thread is interrupted is sub-optimal and I would like to avoid this.
public class ThreadTest
{
public static void main(final String[] args) throws InterruptedException
{
final Thread outerThread = new Thread()
{
#Override
public void run()
{
// Need to externally monitor the thread to detect and process interrupts (for cancellation)
final Thread thread = Thread.currentThread();
new Thread()
{
#Override
public void run()
{
while (true)
{
try
{
Thread.sleep(500);
}
catch (final InterruptedException e)
{}
if (thread.isInterrupted())
{
// Then kill it
thread.stop();
return;
}
}
}
}.start();
uninterruptibleForever();
}
};
outerThread.start();
// Ensure the thread has time to start up
Thread.sleep(500);
outerThread.interrupt();
// The thread should terminate at this point and not continue.
}
/** Some arbitrary task that runs forever and ignores interrupts */
public static void uninterruptibleForever()
{
while (true)
{
System.out.println(MessageFormat.format("I''m still running at {0}", new Date().toLocaleString()));
}
}
}
I can't recommend strongly enough that you don't use Thread#stop().
It should never have existed, was deprecated very quickly and frankly should have been removed about 20 years ago.
You have no idea what the thread is doing when you stop it and it is very easy to corrupt shared objects and leave external resources (e.g. files) in an invalid state.
Suppose the thread is in the middle of resizing a shared ArrayList<> there's risk the object will be corrupted and your whole program fails intermittently in ways you cannot fix.
Do not use Thread#stop() it is broken and cannot be fixed.
It's a terrible feature of Java that it leads people into invalid techniques regarding threads.
Caveat over - how about just overriding interrupt() in a sub-class?
public void interrupt(){
this.stop();
}
You've decided to sub-class Thread (rather than Runnable) so this will "work". "work" in the sense of what you're doing. Not actually work or anything.
The only valid way to solve this is have the thread you want to terminate co-operate by responding to interrupt() as an instruction to come to a suitable point and then terminate cleanly.
Or you can create another flag indicating the thread should end.
I don't know why you need to monitor the thread externally. But here is a small sample how you could do it if you really need it:
import java.util.LinkedList;
import java.util.List;
public abstract class MonitoredCallable implements Runnable {
private final List<InterruptedHandler> interruptedHandlers = new LinkedList<>();
protected abstract void runInternal() throws Exception;
#Override
public final void run() {
try {
runInternal();
} catch(Exception ex) {
}
for (InterruptedHandler interruptedHandler : interruptedHandlers) {
interruptedHandler.threadInterrupted(this);
}
}
public void addInterruptedHandler(InterruptedHandler interruptedHandler) {
this.interruptedHandlers.add(interruptedHandler);
}
public static interface InterruptedHandler {
void threadInterrupted(Thread t);
}
}
Now just use it like this:
MonitoredThread mt = new MonitoredThread() {
#Override
protected void runInternal() throws Exception {
//dosomething
}
};
mt.addInterruptedHandler(t->t.stop());
While using Unirest, the program doesn't exit until we manually shutdown every thread by invoking Unirest.shutdown(). If I had to make just one request, it's easy:
private static void asyncRequest (String link) {
try {
Future <HttpResponse <JsonNode>> request = Unirest.head(link).asJsonAsync(
new Callback<JsonNode>() {
#Override
public void completed(HttpResponse<JsonNode> httpResponse) {
print(httpResponse.getHeaders());
try {
Unirest.shutdown();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void failed(UnirestException e) {
print(e.getMessage());
}
#Override
public void cancelled() {
print("Request cancelled");
}
}
);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
asyncRequest("https://entrepreneur.com");
}
But I have to make multiple HTTP request in parallel (subsequent requests are meant not to wait for previous requests to complete). In the code above, I have to execute the code inside asyncRequest more than once with different links. The problem is I can't decide when to invoke Unirest.shutdown() so that the program exits as soon as the last request receives response. If I call Unirest.shutdown() after all the calls to asyncRequest in main, some or all the requests might get interrupted. If I call it inside completed (and other overridden methods), only the first request is made and others are interrupted. How can I solve this?
In theory, you could make the current thread wait for the execution of the method and after they are all done you can call the shutdown. But this would make the whole process synchronous, which is not what we want. So what I would do is, run different thread (other than the main one) which will wait for the execution of all your http requests. To do so you can use the class CountDownLatch, initializing with the countdown before it releases the control to the parent thread. You pass the instance of the CountDownLatch to the async method and you decrease by one each time you complete an http request. When it reaches 0 it returns the control to the parent thread, where you know you can call shutdown method as all your requests are done.
I have a servlet which is used for a long process which takes minutes to complete. Upon receiving a request to this servlet, the long process is executed inside a thread in order to send the response back to the client immediately due to timeout issues:
public class TestServlet extends HttpServlet {
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
//Thread safe code
Thread thread = new Thread() {
public void run() {
try {
Thread.sleep(10000); //simulate long processing
} catch(InterruptedException v) {
}
}
};
thread.start();
}
}
This means that every time I receive a request, a new thread is created. In order not to run into the risk of attacks, I need to control how many threads are allowed. This means having a pool in the context, and implementing a fail-fast if all threads are busy.
I was looking at the Executor interface. My question is, how can I implement this Thread Pool Executor to be accessible from all the requests received and act as a queue for all the threads? Should I declare the executor as a local non-thread safe variable in the servlet to be accessible by all instances of this servlet as shown below?
public class TestServlet extends HttpServlet {
//non-thread safe variables
//declare executor here
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
//instantiate executor in case it is null
Thread thread = new Thread() {
public void run() {
try {
Thread.sleep(10000); //simulate long processing
} catch(InterruptedException v) {
}
}
};
//add thread to the executor
}
}
Or is it possible to declare this executor at context level?
I was looking also at the Tomcat Executor, which I believe is used by Tomcat itself to manage its thread. Would it be possible to also add these threads to this executor as well?
Usually doing explicit thread management in an app server is a bad idea. You could set up the servlet to run in a new thread itself, and thus avoid farming things out to another thread inside the servlet. I haven't looked up whether Tomcat lets you configure the maximum number of simultaneous instances of a servlet allowed, so that might remain an issue.
If you do explicitly use 'Thread.sleep()', don't abandon the 'InterruptedException' like that. It's the wrong thing to do. Look up the right thing (handle and re-interrupt).
I'm using commons VFS to monitor certain folder for changes (mainly inserting new file), the program should runs permanently, I use the following code
FileSystemManager fsManager = VFS.getManager();
FileObject listendir = fsManager.resolveFile(path);
DefaultFileMonitor fm = new DefaultFileMonitor(new VfsListener());
fm.setRecursive(true);
fm.addFile(listendir);
fm.start();
where path is the folder path, and VfsListener is a class that implements FileListener, when I run the program it runs and then closed immediately, when I added this after fm.start() :
Thread.sleep(100000)
the program run for a while and then closed after the time out is reached, and I don't want that, I want the program to rum permanently, if anyone know please reply
VFS starts the FileMonitor thread as a daemon thread in low priority. The definition of the method setDaemon(boolean) states that
Marks this thread as either a daemon thread or a user thread. The
Java Virtual Machine exits when the only threads running are all
daemon threads.
This method must be called before the thread is started.
This is the reason your program works as long as you 'sleep' in the main thread. However, this is only an issue if you're running this program as a standalone java program. If you run the same piece of code in a application server like Jboss, the code just works fine.
If you still want the standalone program to wait indefinitely, you can modify the program to use a ThreadPoolExecutor which will essentially wait for the new tasks to be available in the Task Queue.
public static void main(String[] args) throws FileSystemException {
Executor runner = Executors.newFixedThreadPool(1);
runner.execute(new Runnable() {
#Override
public void run() {
FileObject listendir = null;
try {
FileSystemManager fsManager = VFS.getManager();
listendir = fsManager.resolveFile(absolutePath);
} catch (FileSystemException e) {
e.printStackTrace();
}
DefaultFileMonitor fm = new DefaultFileMonitor(new FileListener() {
#Override
public void fileDeleted(FileChangeEvent event) throws Exception {
System.out.println(event.getFile().getName().getPath()+" Deleted.");
}
#Override
public void fileCreated(FileChangeEvent event) throws Exception {
System.out.println(event.getFile().getName().getPath()+" Created.");
}
#Override
public void fileChanged(FileChangeEvent event) throws Exception {
System.out.println(event.getFile().getName().getPath()+" Changed.");
}
});
fm.setRecursive(true);
fm.addFile(listendir);
fm.start();
}
});
}
Hope this helps.
Looking at the code block in the Java library AsyncHttpClient, the client starts a new thread (a Future) to make the request. Will the callback happen on the same thread, or will it run on the "main" thread (in this case, the thread where new AsyncHttpClient() was called?
import com.ning.http.client.*;
import java.util.concurrent.Future;
AsyncHttpClient asyncHttpClient = new AsyncHttpClient();
asyncHttpClient.prepareGet("http://www.ning.com/ ").execute(new AsyncCompletionHandler<Response>(){
#Override
public Response onCompleted(Response response) throws Exception{
// Do something with the Response
// ...
return response;
}
#Override
public void onThrowable(Throwable t){
// Something wrong happened.
}
});
the client starts a new thread (a Future) to make the request.
Nope. The Future basically means: this method already returned but it didn't yet finished processing. The processing will continue in background (in some other thread you have no control over) and will finish some time in the future. You can ask this Future object to see whether the future already came or not (processing is done). You are not creating any thread yourself.
Think about ExecutorService. You are submitting some task to be done and waiting for a result. But instead of blocking, you get a Future which will give you back the result as soon as your submitted task reaches the thread pool and is processed.
Will the callback happen on the same thread, or will it run on the "main" thread
Neither. Your thread (the one that called AsyncHttpClient.execute()), by the time the response came back, is most likely doing something completely different. Maybe it serves another client or is already dead. You cannot just call arbitrary code on behalf of some thread.
In fact, this piece of code will be executed by internal NIO thread created by AsyncHttpClient library. You have absolutely no control over this thread. But you have to remember that this will happen asynchronously, so synchronization or some locking might be required if you access global objects.
You can check that by that piece of code:
import java.io.IOException;
import com.ning.http.client.AsyncCompletionHandler;
import com.ning.http.client.AsyncHttpClient;
import com.ning.http.client.Response;
public class Asink {
public static void main(String... args) throws IOException {
AsyncHttpClient asyncHttpClient = new AsyncHttpClient();
asyncHttpClient.prepareGet("http://www.google.com/").execute(
new AsyncCompletionHandler<Response>() {
#Override
public Response onCompleted(Response response)
throws Exception {
// Do something with the Response
// ...
String threadName = Thread.currentThread().getName();
System.out.println(threadName);
return response;
}
#Override
public void onThrowable(Throwable t) {
// Something wrong happened.
}
});
}
}