I have an web application which accept some data from user to create a task, then the task should be executed.
Since the execution of the Task is to download something from the internet which will cost some time, so I tried to create a new Thread to do the job.
This is my idea:
create a LoaderThread
used to download data. And the LoaderThread
hold a field of ArrayList
used for put the Task
.
A Servlet
to handle the request and response.
When the Servlet
startup, start the LoaderThread
During the servlet run, add task to the LoaderThread
.
This is the code(some of them is omitted):
public class RwdServlet extends HttpServlet {
private StaticMapLoader loader;
@Override
public void init() throws ServletException {
super.init();
loader = new StaticMapLoader();
loader.startRunning();
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Task t=createTask(req);
loader.addTask(t);
}
@Override
public void destroy() {
loader.stopRunning();
}
}
public class StaticMapLoader extends Thread {
private List<Task> tasks = new ArrayList<Task>();
private boolean running = false;
@Override
public void run() {
while (running) {
if (tasks.size() > 0) {
Task t = tasks.get(0);
log.info(t);
if (t != null && t.status == Status.waiting) {
tasks.remove(0);
t.status = Status.running;
downLoad(t);
}
}
}
}
private void downLoad(Task t) {
//download file
}
public void addTask(Task t) {
tasks.add(t);
}
public void startRunning() {
running = true;
this.start();
}
public void stopRunning() {
running = false;
this.interrupt();
}
}
The above code worked, but I found that even the tasks
were empty and there are no new task
added, the loop will keep running.
So I though if I can make the LoaderThread
suspend when there are no tasks, and notify it when new task come out.
So I tried this:
@Override
public void run() {
while (running) {
if (tasks.size() > 0) {
Task t = tasks.get(0);
log.info(t);
if (t != null && t.status == Status.waiting) {
tasks.remove(0);
t.status = Status.running;
downLoad(t);
}
} else {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
I tried to call the wait()
if the tasks
is empty.
But I do not know how to wake up it?
Also, is there anything I should know to improve the application?
BWT, is it possible that more than one LoaderThread
instance will be created? If so , how to avoid it?
It seems that I can use other implementation, but I wonder if my case is refactor-able?
Since I want to learn some thing I have missed. :) Thanks.
Your requirements are the standard usage of ExecutorService , so I would recommend you to use ExecutorService and not reinvent the wheel.
Base on code you provided, your servlet should look like this:
public class RwdServlet extends HttpServlet {
private ExecutorService loader;
@Override
public void init() throws ServletException {
super.init();
loader = Executors.newCachedThreadPool();//or use some other executor, google about difference between them
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Task t=createTask(req); //assume that task implements Runnable or Callable
loader.submit(t); // submit a task to executor after this line your task will start execution in another thread
}
@Override
public void destroy() {
loader.shutdown();//this will destroy executor service but before that it will wait until all already submitted tasks will be executed
}
}
Your use case calls for an ExecutorService and you have started reimplementing it from scratch. Better stop now and use the finished, bug-free, flexible, and powerful product from the standard library.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.