2013-09-25 86 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