2013-09-25 75 views
0

我有一个Web应用程序,它接受用户创建任务的一些数据,然后执行任务。java线程等待并自动唤醒

由于任务的执行是从互联网上下载一些需要花费一些时间的东西,所以我尝试创建一个新的线程来完成这项工作。

这是我的想法:

  1. 创建用于下载数据的LoaderThread。并且LoaderThread持有ArrayList用于放置Task的字段。

  2. A Servlet来处理请求和响应。

  3. Servlet启动,启动LoaderThread

  4. 在servlet的运行中,添加任务的LoaderThread

这是代码(其中一些被省略):上面的代码工作

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

,但我发现,即使是tasks是空的,没有新的task增加,循环将继续运行。

所以我虽然可以让LoaderThread在没有任务时暂停,并在新任务出来时通知它。

所以,我想这一点:

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

     } 
    } 
} 

我试着拨打wait()如果tasks是空的。

但我不知道如何醒来呢?

此外,有什么我应该知道,以改善应用程序?

BWT,是否有可能会创建多个LoaderThread实例?如果是这样,如何避免它?


看来我可以使用其他实现,但我不知道我的情况是否可以重构?

因为我想了解一些我错过的东西。 :) 谢谢。

回答

2

您的要求是ExecutorService的标准用法,所以我建议您使用ExecutorService而不是重新发明轮子。

此基础上你提供的代码,你的servlet应该是这样的:

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 

    } 
} 

link with example

+0

'ExecutorService'能否自动等待并唤醒? – hguser

+0

你是什么意思自动唤醒?当您初始化它时,并且在“待机模式”下提交任务'ExecutorService'之前。提交任务后,它开始异步计算。 – nkukhar

+0

如何完成所有任务,ExecutorService会再次处于“待命”状态,过了一段时间后,如果将新任务添加到任务中,它会启动吗? – hguser

0

你的使用情况要求一个ExecutorService,你已经开始从头开始重新实现它。现在更好地停下来,使用标准库中已完成的,无缺陷,灵活且功能强大的产品。

+0

我很抱歉,但我不完全确定你的意思。你推荐我使用'ExecutorService'还是不? – hguser

+0

@hguser:我很确定他意味着你正在尝试构建已经存在的东西,所以你应该停止浪费你的时间并使用更好的库。除非你有惊人的技能,否则你的结果不会比现有的好。 :) – Izmaki

+0

@lzmaki:谢谢,我明白了。 – hguser