簡體   English   中英

如何強制執行Singleton(一個ScheduledExecutorService的全局實例),一次執行一項任務?

[英]How to enforce singleton (one global instance of) ScheduledExecutorService, one task at a time?

我有一個需要從服務器請求數據的應用程序,有時是一次性請求,而其他時候則需要以固定速率輪詢。

對於一個關閉的請求,我只使用如下線程:

    public void request() {
        Thread requestThread = new Thread(this);
        requestThread.start();
    }

這些沒問題,先執行,然后完成。

但是,對於長時間的輪詢任務,我似乎永遠無法一次只執行其中之一。

我想要的是以下方法:

    public void longPoll() {
        try {
            pollingScheduledExecutor.scheduleAtFixedRate(this, 0, 3, TimeUnit.SECONDS);
        } catch (Exception ignored) {
        }
    }

曾經只能存在一次,但是現在發生的是,當我從第一個類調用它時,它通常開始,但是從第二個任務調用后,它永遠不會停止。

如何強制該ScheduledExecutorService只有一個全局實例?

對於上下文,這是這些方法所在的類:

public abstract class AbstractCommunicationChannel implements Runnable {
    static String SERVER_ADDRESS = "http://0.0.0.0";

    private URL url;
    private JSONObject requestObject;
    private JSONObject responseObject;

    private volatile ScheduledExecutorService pollingScheduledExecutor = Executors.newSingleThreadScheduledExecutor();

    public void longPoll() {
        try {
            pollingScheduledExecutor.scheduleAtFixedRate(this, 0, 3, TimeUnit.SECONDS);
        } catch (Exception ignored) {
        }
    }

    public void request() {
        Thread requestThread = new Thread(this);
        requestThread.start();
    }

    AbstractCommunicationChannel(URL url, JSONObject requestObject) {
        this.url = url;
        this.requestObject = requestObject;
    }

    /**
     * This is the general purpose tool for hitting the server and getting a response back.
     */
    public void run() {
        Log.i("requestObject", requestObject.toString());
        try {
            HttpURLConnection httpUrlConnection = (HttpURLConnection) url.openConnection();
            httpUrlConnection.setDoOutput(true);
            httpUrlConnection.setRequestMethod("POST");
            httpUrlConnection.setRequestProperty("Content-Type", "application/json; charset=utf-8");

            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(httpUrlConnection.getOutputStream());
            outputStreamWriter.write(requestObject.toString());
            outputStreamWriter.flush();
            outputStreamWriter.close();
            /* * */
            InputStream inputStream = httpUrlConnection.getInputStream();
            BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            int result = bufferedInputStream.read();
            while (result != -1) {
                byteArrayOutputStream.write((byte) result);
                result = bufferedInputStream.read();
            }
            responseObject = new JSONObject(byteArrayOutputStream.toString("UTF-8"));
            httpUrlConnection.disconnect();
        } catch (Exception ignored) {
        }
        processResponse(responseObject);
    }

    protected abstract void processResponse(JSONObject responseObject);
}

又是我。

如果只需要一個正在運行的輪詢任務,則必須取消前一個任務(如果已存在)。

例:

private static final Object lock = new Object();
private static ScheduledFuture<?> currentRunningTask;

    public void longPoll() {

        synchronized (lock) {

            if (currentRunningTask != null) {
                currentRunningTask.cancel(true);
            }

            try {
                currentRunningTask = pollingScheduledExecutor.scheduleAtFixedRate(this, 0, 3, TimeUnit.SECONDS);
            } catch (Exception ignored) {
                ignored.printStackTrace();
            }
        }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM