0

我有一个 Web 应用程序,它接受来自用户的一些数据来创建任务,然后应该执行该任务。

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

这是我的想法:

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

  2. AServlet处理请求和响应。

  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实例?如果是这样,如何避免呢?


看来我可以使用其他实现,但我想知道我的案例是否可以重构?

因为我想学习一些我错过的东西。:) 谢谢。

4

2 回答 2

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

    }
}

请参阅示例链接

于 2013-09-25T10:08:18.243 回答
0

您的用例需要一个 ExecutorService 并且您已经开始从头开始重新实现它。现在最好停下来,使用标准库中已完成、无错误、灵活且功能强大的产品。

于 2013-09-25T10:09:10.897 回答