有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

多线程java线程等待和自动唤醒

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

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

这是我的想法:

  1. 创建用于下载数据的LoaderThread。并且LoaderThread保存用于放置TaskArrayList字段

  2. 一个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();
            }

        }
    }
}

如果tasks为空,我尝试调用wait()

但我不知道如何唤醒它

还有,我应该知道什么来改进应用程序吗

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


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

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


共 (2) 个答案

  1. # 1 楼答案

    你的要求是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

  2. # 2 楼答案

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