[concurrency-interest] Simple ScheduledFuture problem

robert lazarski robertlazarski at gmail.com
Thu Aug 17 10:56:19 EDT 2006


Thanks Dave and Joe. I implemented the changes you two mentioned (I
hope) and now invoke a FutureTask inside the Runnable of the
ScheduledFuture . Here's what I came up with. The purpose here is just
to simply record the states of an app server.

Thanks!
Robert

package org;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class Ping {

      private volatile int  flag = 0;
      private static int STOPPED = new Integer(0);
      private static int BEGIN_INIT = new Integer(1);
      private static int RUNNING = new Integer(2);
          private static Map <Integer, String> map;

      /** commons logging declaration. */
      private static Log logger = LogFactory.getLog(
                Ping.class);

      public static void main(String[] args) throws Exception {

              new Ping();
      }

      Ping () {
          ScheduledExecutorService ses =
Executors.newSingleThreadScheduledExecutor();
          // Do pings, starting now, with a 2 second delay in between
          ScheduledFuture <?> ping = ses.scheduleWithFixedDelay(new PingTask(),
              0L, 2000L, TimeUnit.MILLISECONDS);
      }

      static {
          map = new HashMap<Integer, String>();
          map.put(STOPPED, "STOPPED");
          map.put(BEGIN_INIT, "BEGIN_INIT");
          map.put(RUNNING, "RUNNING");
      }

      private synchronized void setFlag(int var) {
          flag = var;
      }

      /** Get message via an int.
       * @param code Integer mapped to message
       * @return String mapped message
       */
      public final String getMessage(int code) {
          return map.get(code);
      }

      class PingFuture implements Runnable {
          private void doConnect(String host, int port, boolean
on_connect, int state) {
              try {
                  logger.debug("connecting to host: " +host+ ", port: " + port);
                  InetAddress addr = InetAddress.getByName(host);
                  // will throw an exception if could not connect
                  Socket s = new Socket(addr, port);
                  s.close();
                  if (on_connect) {
                      logger.debug("Found port: " + port);
                      setFlag(state);
                  }

              } catch (Exception ex) {
                  logger.error("Can't find port: " + port);
                  logger.error(ex.getMessage(), ex);
                  if (!on_connect) {
                      setFlag(state);
                  }
              }

          }

          private void doConnect(URL host, boolean on_connect, int
state) throws IOException {
              InputStream is = null;
              BufferedReader in = null;
              try {
                  logger.debug("connecting to url: " + host.toString());
                  URLConnection uc = host.openConnection();
                  if (uc == null) {
                      logger.error("Got a null URLConnection object!");
                      return;
                  }
                  is = uc.getInputStream();
                  if (is == null) {
                      logger.error("Got a null content object!");
                      return;
                  }
                  in = new BufferedReader(new InputStreamReader(
                        is));
                  String inputLine;
                  // just test that its readable for now
                  while ((inputLine = in.readLine()) != null)  {
                        ;
                  }
                  if (on_connect) {
                      logger.debug("Found url: " + host.toString());
                      setFlag(state);
                  }

              } catch (Exception ex) {
                  logger.error("Can't find url: " + host.toString());
                  logger.error(ex.getMessage(), ex);
                  if (!on_connect) {
                      setFlag(state);
                  }
              } finally {
                  if (is != null) {
                      is.close();
                  }
                  if (in != null) {
                      in.close();
                  }
              }

          }

          public void run() {

              try {
                  if (flag == STOPPED) {
                      doConnect("localhost", 1099, true, BEGIN_INIT);
                  }
                  if (flag == BEGIN_INIT) {
                      // test state of stopped to prevent endless loop
                      doConnect("localhost", 1099, false, STOPPED);
                      doConnect(new
URL("http://localhost:8080/maragato/"), true, RUNNING);

                  }
                  if (flag == RUNNING) {
                      doConnect(new
URL("http://localhost:8080/maragato/"), false, STOPPED);
                  }

              } catch (Exception ex) {
                    logger.error(ex.getMessage(), ex);
              }
          }
      } // end inner class PingFuture

      class PingTask implements Runnable {

          public void run() {

              try {
                  FutureTask<?> f = new FutureTask<Object>(new
PingFuture(), null);
                  Thread thread = new Thread(f);
                  thread.start();
                  // 5 seconds to finish connect or will timeout
                  f.get(5000, TimeUnit.MILLISECONDS);
              } catch (Exception ex) {
                    logger.error(ex.getMessage(), ex);
              }
              finally {
                  logger.debug("CURRENT STATE: " + getMessage(flag));

              }
          }
      } // end inner class PingTask

}


On 8/16/06, Joe Bowbeer <joe.bowbeer at gmail.com> wrote:
> At a glance, I notice a few things that could be cleaned up, though
> they may have no impact on the problem.
>
> 1. setFlag is synchronized but there is no synchronized getFlag method.
>
> Either added synchronized getFlag, or declare flag to be "volatile".
>
> 2. doConnect(url) code may fail without closing input stream.
>
> Add try-catch after opening input stream.
>
> 3. Also, I would consider switching to fixed delay to avoid the
> possibility of multiple outstanding pings.
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at altair.cs.oswego.edu
> http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
>


More information about the Concurrency-interest mailing list