简体   繁体   中英

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

I've got an application that needs to request data from the server, sometimes as a one off request, other times it needs to poll at a fixed rate.

For the one off requests I just use a thread like so:

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

These are ok, they execute and then they're done.

However, for the long polling tasks, I can never seem to have only one of them executing at a time.

What I want is that the following method:

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

Would only ever be able to exist once, but what's happening now is that when I call it from the first class it begins normally, but it doesn't ever stop after it's call from the second task.

How to enforce that there's only one global instance of this ScheduledExecutorService ?

For context, here is the class wherein these methods live:

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);
}

its again me.

If you want only one running polling task, you have to cancel the previous one if already exist.

Example:

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();
            }
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM