0

ユーザーからデータを受け取ってタスクを作成する Web アプリケーションがあり、タスクを実行する必要があります。

タスクの実行はインターネットから何かをダウンロードすることなので、時間がかかります。そのため、仕事をするために新しいスレッドを作成しようとしました。

これは私の考えです:

  1. LoaderThreadデータをダウンロードするために使用されるを作成します。そして、プットのためLoaderThreadに使用されるホールドフィールド。ArrayListTask

  2. Servletリクエストとレスポンスを処理するための A。

  3. Servlet起動したら、LoaderThread

  4. サーブレットの実行中に、タスクを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使用し、車輪を再発明しないことをお勧めします。

提供したコードに基づいて、サーブレットは次のようになります。

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 に答える