I m having a java server which is processing images as in the web pages requested by the client.
Now processing these images requires time and memory and n number of threads going into the processing images hangs the server.
Now for avoiding the situation the code which processes the images, i have put them inside a Runnable class and calling them from a executor pool.
My question is if the below implementation is right approach to execute the Executor pool in a server.
The Runnable class being -
public class MyRunnable implements Runnable {
private final String id;
MyRunnable(String tid) {
this.id = tid;
}
#Override
public void run() {
NewAlbumImage nai = new NewAlbumImage();
nai.save_image(id,false);
}
}
The code which runs the Runnable class is as below -
newa.NewClass newca = new newa.NewClass();
Runnable mr = new MyRunnable(id);
newca.executor.execute(mr);
The class NewClass has a static executor variable -
static ExecutorService executor;
I m initializing the executor variable at the web applictation startup and destroying the same at the web application close -
public class AppNameServletContextListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("Initializing Executor Pool");
NewClass nc = new NewClass();
nc.executor = Executors.newFixedThreadPool(10);
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
NewClass nc = new NewClass();
nc.executor.shutdown();
try {
nc.executor.awaitTermination( 10L, TimeUnit.MINUTES);
} catch (InterruptedException ex) {
System.out.println("Executor Pool await Termination exception");
}
}
}
There are some things I would consider.
First, your executor is static. I'd use some sort of dependency injection framework to properly inject your the executor where needed. OR add it as an attribute in your servlet context and inject it yourself when the servlet initializes.
Create/Shutdown using the ServletContext:
#Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext context = sce.getServletContext();
context.setAttribute("executor", Executors.newCachedThreadPool());
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
ServletContext context = sce.getServletContext();
ExecutorService executor = (ExecutorService)context.getAttribute("executor");
executor.shutdown();
}
Secondly, you are using a fixed thread pool. This is a possible bottleneck (but maybe it's deliberate to save the CPU?). If there's no way more that 10 images could be resized at the same time, you're fine. But if the rate at which they are being processed is slower than the rate that requests are coming in, you are going to find that a fixed thread pool is not going to work. In fact, if your application joins on the resizing task for the response back to the user, you've limited the number of possible request at any given moment to the number of threads defined. Try using a cached thread pool. Threads are created on demand and die from inactivity.
Executors.newCachedThreadPool();
Lastly, and I think this is more important, how is you application going to scale? The more users you have, the more images that are going to be processed on your web-server. Your response time is going to degrade very quickly. As few as three users trying to resize images at the same time could use 100% of your CPU. I'd suggest farming out your image resizing to another machine, one more capable.
You mentioned that
The class NewClass has a static executor variable -
static ExecutorService executor;
I suggest to use
NewClass.executor.execute(yourRunnableInstance);
NewClass.executor.shutdown();
This will be easy to figure out that executor is a static field, you don't need to create multiple NewClass instances.
The rest of the code looks fine.
Related
Threads add a lot of verbal to the code and make it harder to understand and reason about. Look at this code for example:
public class ConnectionListener implements Runnable {
private Thread thread;
private boolean running;
public void start() {
if (!running) {
thread = new Thread(this);
thread.start();
}
}
public void stop() {
if (running) {
running = false;
thread.interrupt();
}
}
#Override
public void run() {
running = true;
while (running) {
// Do some crap
}
}
}
The whole concern of this class should be listening for connection requests from the network. But look how many lines of code are added just for managing a thread. Is there any way to make this code cleaner?! I don't want to see the thread = new Thread();, not the thread variable and not any of the stop()/start() methods!
Of course I know what the ExecutorService is... But what if I want to manage a long-running thread? By long-running thread, I mean a thread with a life cycle long as the application's life cycle.
Do you have any good solution for me? A way to remove the thread creation and management concerns from a class without making the class extend another class?
I solved the problem by using a single-threaded executor service. I've also read about the performance differences between Plain Thread, ThreadPool and SingleThreadExecutor - SingleThreadExecutor VS plain thread.
Using a single thread executor allows me to start a single thread and manage it using its Future. See code example:
public void func(String[] args) {
ExecutorService es = Executors.newSingleThreadExecutor();
Future<?> f = es.submit(Some Runnable);
}
Thanks to #BasilBourque that gave me this solution in the comments.
I would like to execute the following JAVA code only once when I enter to welcome.jsp page.
welcome.jsp:
<%WeeklyScheduledMail wsm = WeeklyScheduledMail.INSTANCE;
wsm.startThread(); %>
So, if a user access to the website once the server is initiated, that code can be used once, and the other users who log in and access to welcome.jsp will not execute that JAVA code.
First, I tried to implement the Singleton pattern with enum, I thought it would be enough but it did not work. I also tried the Synchronized keyword for the methods but nothing...
I'm sure I did something wrong or there is a better way to do what I want to do.
Some portions of the code:
WeeklyScheduledMail.java:
public enum WeeklyScheduledMail{
INSTANCE;
public void startThread() {
ScheduledExecutorService scheduler =
Executors.newSingleThreadScheduledExecutor();
Runnable task = new TaskSendEmail();
int initialDelay = 0;
int periodicDelay = 10;
scheduler.scheduleAtFixedRate(task, initialDelay, periodicDelay,
TimeUnit.SECONDS);
}
}
TaskSendEmail.java:
public class TaskSendEmail implements Runnable{
public void run() {
System.out.println("Hello: "+System.currentTimeMillis());
}
}
You're looking into the incorrect concept to run application initialization code. JSPs and other resources exposed to the user aren't designed for this. Even if you can force some lazy initialization logic, there will still be avoidable overhead.
What you're looking for is provided by JavaEE: a context listener, which is invoked once on application startup to notify your application that the context has been initialized:
public class MyContextListener implements javax.servlet.ServletContextListener {
private static fWeeklyScheduledMail wsm =
weeklyScheduledMail.INSTANCE;
#Override
public void contextInitialized(ServletContextEvent sce) {
wsm.startThread();
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
wsm.stopThread();
}
}
This listener must then be registered in the web.xml deployment descriptor (under web-app):
<listener>
<listener-class>my.packg.MyContextListener</listener-class>
</listener>
The above code and configuration will cause your schedule to run once, when the application starts.
I am developing an API. This API needs to do 2 DB queries to get the result.
I tried following strategies:
Used callable as return type in Controller.
Created 2 threads in Service (use Callable and CoundownLatch) to run 2 queries parallel and detect finishing time.
public class PetService {
public Object getData() {
CountDownLatch latch = new CountDownLatch(2);
AsyncQueryDBTask<Integer> firstQuery= new AsyncQueryDBTask<>(latch);
AsyncQueryDBTask<Integer> secondQuery= new AsyncQueryDBTask<>(latch);
latch.await();
}
public class AsyncQueryDBTask<T> implements Callable {
private CountDownLatch latch;
public AsyncQueryDBTask(CountDownLatch latch) { this.latch = latch;}
#Override
public T call() throws Exception {
//Run query
latch.countDown();
}
It worked fine but I feel that I am breaking the structure of Spring somewhere.
I wonder what is the most efficient way to get data in Spring 4.
-How to know both of 2 threads that run own query completed their job?
-How to control thread resource such as use and release thread?
Thanks in advance.
You generally don't want to create your own threads in an ApplicationServer nor manage thread lifecycles. In application servers, you can submit tasks to an ExecutorService to pool background worker threads.
Conveniently, Spring has the #Async annotation that handles all of that for you. In your example, you would create 2 async methods that return a Future :
public class PetService {
public Object getData() {
Future<Integer> futureFirstResult = runFirstQuery();
Future<Integer> futureSecondResult = runSecondQuery();
Integer firstResult = futureFirstResult.get();
Integer secondResult = futureSecondResult.get();
}
#Async
public Future<Integer> runFirstQuery() {
//do query
return new AsyncResult<>(result);
}
#Async
public Future<Integer> runSecondQuery() {
//do query
return new AsyncResult<>(result);
}
}
As long as you configure a ThreadPoolTaskExecutor and enable async methods, Spring will handle submitting the tasks for you.
NOTE: The get() method blocks the current thread until a result is returned by the worker thread but doesn't block other worker threads. It's generally advisable to put a timeout to prevent blocking forever.
I am trying to figure out how to use the types from the java.util.concurrent package to parallelize processing of all the files in a directory.
I am familiar with the multiprocessing package in Python, which is very simple to use, so ideally I am looking for something similar:
public interface FictionalFunctor<T>{
void handle(T arg);
}
public class FictionalThreadPool {
public FictionalThreadPool(int threadCount){
...
}
public <T> FictionalThreadPoolMapResult<T> map(FictionalFunctor<T> functor, List<T> args){
// Executes the given functor on each and every arg from args in parallel. Returns, when
// all the parallel branches return.
// FictionalThreadPoolMapResult allows to abort the whole mapping process, at the least.
}
}
dir = getDirectoryToProcess();
pool = new FictionalThreadPool(10); // 10 threads in the pool
pool.map(new FictionalFunctor<File>(){
#Override
public void handle(File file){
// process the file
}
}, dir.listFiles());
I have a feeling that the types in java.util.concurrent allow me to do something similar, but I have absolutely no idea where to start.
Any ideas?
Thanks.
EDIT 1
Following the advices given in the answers, I have written something like this:
public void processAllFiles() throws IOException {
ExecutorService exec = Executors.newFixedThreadPool(6);
BlockingQueue<Runnable> tasks = new LinkedBlockingQueue<Runnable>(5); // Figured we can keep the contents of 6 files simultaneously.
exec.submit(new MyCoordinator(exec, tasks));
for (File file : dir.listFiles(getMyFilter()) {
try {
tasks.add(new MyTask(file));
} catch (IOException exc) {
System.err.println(String.format("Failed to read %s - %s", file.getName(), exc.getMessage()));
}
}
}
public class MyTask implements Runnable {
private final byte[] m_buffer;
private final String m_name;
public MyTask(File file) throws IOException {
m_name = file.getName();
m_buffer = Files.toByteArray(file);
}
#Override
public void run() {
// Process the file contents
}
}
private class MyCoordinator implements Runnable {
private final ExecutorService m_exec;
private final BlockingQueue<Runnable> m_tasks;
public MyCoordinator(ExecutorService exec, BlockingQueue<Runnable> tasks) {
m_exec = exec;
m_tasks = tasks;
}
#Override
public void run() {
while (true) {
Runnable task = m_tasks.remove();
m_exec.submit(task);
}
}
}
How I thought the code works is:
The files are read one after another.
A file contents are saved in a dedicated MyTask instance.
A blocking queue with the capacity of 5 to hold the tasks. I count on the ability of the server to keep the contents of at most 6 files at one time - 5 in the queue and another fully initialized task waiting to enter the queue.
A special MyCoordinator task fetches the file tasks from the queue and dispatches them to the same pool.
OK, so there is a bug - more than 6 tasks can be created. Some will be submitted, even though all the pool threads are busy. I've planned to solve it later.
The problem is that it does not work at all. The MyCoordinator thread blocks on the first remove - this is fine. But it never unblocks, even though new tasks were placed in the queue. Can anyone tell me what am I doing wrong?
The thread pool you are looking for is the ExecutorService class. You can create a fixed-size thread pool using newFixedThreadPool. This allows you to easily implement a producer-consumer pattern, with the pool encapsulating all the queue and worker functionality for you:
ExecutorService exec = Executors.newFixedThreadPool(10);
You can then submit tasks in the form of objects whose type implements Runnable (or Callable if you want to also get a result):
class ThreadTask implements Runnable {
public void run() {
// task code
}
}
...
exec.submit(new ThreadTask());
// alternatively, using an anonymous type
exec.submit(new Runnable() {
public void run() {
// task code
}
});
A big word of advice on processing multiple files in parallel: if you have a single mechanical disk holding the files it's wise to use a single thread to read them one-by-one and submit each file to a thread pool task as above, for processing. Do not do the actual reading in parallel as it will degrade performance.
A simpler solution than using ExecuterService is to implement your own producer-consumer scheme. Have a thread that create tasks and submits to a LinkedBlockingQueue or ArrayBlockingQueue and have worker threads that check this queue to retrieve the tasks and do them. You may need a special kind of tasks name ExitTask that forces the workers to exit. So at the end of the jobs if you have n workers you need to add n ExitTasks into the queue.
Basically, what #Tudor said, use an ExecutorService, but I wanted to expand on his code and I always feel strange editing other people's posts. Here's a sksleton of what you would submit to the ExecutorService:
public class MyFileTask implements Runnable {
final File fileToProcess;
public MyFileTask(File file) {
fileToProcess = file;
}
public void run() {
// your code goes here, e.g.
handle(fileToProcess);
// if you prefer, implement Callable instead
}
}
See also my blog post here for some more details if you get stuck
Since processing Files often leads to IOExceptions, I'd prefer a Callable (which can throw a checked Exception) to a Runnable, but YMMV.
I have a web application running in tomcat where I'm using a ThreadPool (Java 5 ExecutorService) to run IO intensive operations in parallel to improve performance. I would like to have some of the beans used within each pooled thread be in the request scope, but the Threads in the ThreadPool do not have access to the spring context and get a proxy failure. Any ideas on how to make the spring context available to the threads in the ThreadPool to resolve the proxy failures?
I'm guessing there must be a way to register/unregister each thread in the ThreadPool with spring for each task, but haven't had any luck finding how to do this.
Thanks!
I am using the following super class for my tasks that need to have access to request scope. Basically you can just extend it and implement your logic in onRun() method.
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
/**
* #author Eugene Kuleshov
*/
public abstract class RequestAwareRunnable implements Runnable {
private final RequestAttributes requestAttributes;
private Thread thread;
public RequestAwareRunnable() {
this.requestAttributes = RequestContextHolder.getRequestAttributes();
this.thread = Thread.currentThread();
}
public void run() {
try {
RequestContextHolder.setRequestAttributes(requestAttributes);
onRun();
} finally {
if (Thread.currentThread() != thread) {
RequestContextHolder.resetRequestAttributes();
}
thread = null;
}
}
protected abstract void onRun();
}
I also wish I had 1000 votes to give to the currently accepted answer. I had been stumped on how to do this for some time. Based on it, here is my solution using the Callable interface in case you want to use some of the new #Async stuff in Spring 3.0.
public abstract class RequestContextAwareCallable<V> implements Callable<V> {
private final RequestAttributes requestAttributes;
private Thread thread;
public RequestContextAwareCallable() {
this.requestAttributes = RequestContextHolder.getRequestAttributes();
this.thread = Thread.currentThread();
}
public V call() throws Exception {
try {
RequestContextHolder.setRequestAttributes(requestAttributes);
return onCall();
} finally {
if (Thread.currentThread() != thread) {
RequestContextHolder.resetRequestAttributes();
}
thread = null;
}
}
public abstract V onCall() throws Exception;
}
Could you try it the other way round? Use a data container that's stored in request scope and give it to the thread pool (perhaps put it into a queue, so that the thread pool can take one data container at a time, work on it, mark it as "done" and continue with the next one).
Spring has a ThreadPoolTaskExecutor class that you can use to manage your thread pool from Spring. However, it looks like you'd have to do some work to make the Spring context available to each thread.
I'm not sure if it will work even if you do wire it up this way though. Spring uses a token in thread local to locate objects in request (or session) scope, so if you're trying to access a request scope bean from a different thread, it's likely that token won't be there.