代码之家  ›  专栏  ›  技术社区  ›  smatthewenglish

如何执行ScheduledExecutorService的单例(一个全局实例),一次执行一个任务?

  •  0
  • smatthewenglish  · 技术社区  · 6 年前

    我有一个应用程序需要从服务器请求数据,有时作为一次性请求,有时需要以固定速率轮询。

    对于一次性请求,我只使用如下线程:

        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);
    }
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   HPCS    6 年前

    又是我。

    如果只需要一个正在运行的轮询任务,则必须取消上一个任务(如果已存在)。

    例子:

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