1

Preface: I'm learning Java and not very experienced. My sincere apologies if 1) I'm going about this in a stupid way or 2) My question is unclear. I am eager to learn if my approach is all wrong so please try to show me the light instead of simply telling me I'm in the dark(I'm already well aware I'm surrounded by darkness lol). I will be happy to update/edit this post with any additional information you need, just please ask me. I've tried searching for this but either I'm using the wrong keywords or it's just too stupid a question for anyone to ask.

class NetworkingThread implements Runnable {
    @Override
    public void run() {//Need this to throw SocketException every 10ms
        try {
            DatagramPacket dataPacket = receive(ds);//networkIO blocking
            //do something
            this.run();//recursive call
        }
        catch (SocketException | SocketTimeoutException e0){
            //do something
            this.run();//recursive call
        }
        catch (Exception e1) {
                e1.getMessage();
            }
    }
}

The Problem: The catch block needs to be run at least every 10ms. Cannot use DatagramSocket.setSoTimeout() alone because exception needs to be thrown 10ms after last catch block execution completed not 10ms from last packet received.

My plan: Have the catch block start another thread that will sleep(10) before closing the socket for receive(ds) so that the catch is thrown in my NetworkingThread at the proper time.

Question: Is it better to create a new thread each time I need to start the 10ms counter? Or start one thread and pause execution(not with deprecated API) after it's done it's task and wait for an interrupt to restart it? Examples of what I'm thinking below. Any alternative solutions are welcome.

class TimerThreadOne implements Runnable {
    @Override
    public void run() {
        try {
            Thread.currentThread().sleep(10);
            //close socket or interrupt thread in some way
        }
        catch (Exception e) {
                e.getMessage();
        }
    }
}

class TimerThreadTwo implements Runnable {
    @Override
    public void run() {
        try {
            Thread.currentThread().sleep(10);
            //close socket or interrupt thread in some way
            Thread.currentThread().sleep(1000000);//sleep until interrupted
        }
        catch (InterruptedException eInterrupt){
            this.run();//recursive call
        }
        catch (Exception e) {
                e.getMessage();
        }
    }
}
RoboLam
  • 398
  • 4
  • 14
  • Don't use recursion as an iteration technique. All you're doing is adding yet another failure mode. – user207421 Feb 02 '15 at 09:39
  • As suggested, you should use a `while(true){ }` block for iteration instead of recursion. if you use recursion to create a infinite loop, you are going to have a memory error at some point. – David SN Feb 02 '15 at 10:43
  • Thank you David SN for offering a solution to my mistake. I was under the (mistaken) impression that recusion was the same as while(true){ }. Can someone explain why a recusive call will causes a memory error but a while(true) statement wont? Pointing me to a URL is perfectly fine too :) I'm just curious to learn the why in everything – RoboLam Feb 02 '15 at 18:08
  • 1
    You will get a` StackOverflowException` at some point, because recursion consumes stack via method calls. Iteration via `while (true)` doesn't do that. – user207421 Feb 03 '15 at 06:36

1 Answers1

1

Have a look at ScheduledThreadPoolExecutor which already provides the facility what you look to achieve.

Your code should look something like below.

ScheduledExecutorService executor = Executors.newScheduledThreadPool(someValue);
executor.scheduleWithFixedDelay(new SomeThread(), 0, 10, TimeUnit.MILLISECONDS);

Class SomeThreadwill implement Runnable and contain the business logic; without any consideration of scheduling, re-run etc. apart from any exception handling legitimate to business / system requirements.

P.S.: In general it is not recommended to use Exception as flow control.

EDIT
Timeout waiting on a long running task

    ScheduledExecutorService executor = Executors
            .newScheduledThreadPool(10);
    ScheduledFuture<?> result = executor.scheduleWithFixedDelay(() -> {// do
                                                                        // something
            }, 0, 10, TimeUnit.MILLISECONDS);

    try {
        // this will timeout the task after 5ms. 
        result.get(5, TimeUnit.MILLISECONDS);
    } catch (InterruptedException | ExecutionException | TimeoutException e) {
        // handle exception
        result.cancel(true); 
    }

I took liberty to assume that you are on Java 8

Bond - Java Bond
  • 3,662
  • 6
  • 34
  • 56
  • First off, THANK YOU! Secondly, if using Exception as flow control is not recommended, how should I interrupt a NetworkIO block like DatagramSocket.receive()? Thread.interrupt does not work as while receive() is blocking the thread will not check the interrupt flag. Lastly, I am still unsure if pausing/resuming one thread is better or worse than creating a new thread every so many ms until the application is closed. I assume since my only solution for pause/resume of a thread requires using Exception for flow control your answer would be not to pause/restart it? – RoboLam Feb 02 '15 at 18:39
  • Hope the above didn't come off as rude, char limit made me cut out a lot of pleasantries – RoboLam Feb 02 '15 at 18:46
  • no it didn't !! :) Coming to your questions about pause / resume / interrupt etc, you are in luck as Java has that facility as well. Check the edit for same. – Bond - Java Bond Feb 03 '15 at 06:24
  • Wow, this is perfect! :) Thank you so much! I am using Java 8 but just out of curiosity, (and if you don't mind me asking even more of you) how would this change if I were using Java 7 instead? I'm not, just but I would like to learn and the docs page for 7 looks exactly the same as what you did above to me. – RoboLam Feb 03 '15 at 17:21
  • Oh wait...maybe I misunderstood(very likely and apologies if I did) but doesn't this solution still use require me to use Exception as flow control(albeit less)? The blocking thread will repeatedly timeout and throw an exception which will be caught. Will this not still be a bad idea? P.S. I googled why not to use Exception as flow control and learned a lot. Thank you for that :) – RoboLam Feb 03 '15 at 17:56
  • For Java 7 the LOC `executor.scheduleWithFixedDelay(() -> {// do something }, 0, 10, TimeUnit.MILLISECONDS);` will look like this instead `executor.scheduleWithFixedDelay(new SomeThread(), 0, 10, TimeUnit.MILLISECONDS);`. (*note the lambda is replaced by traditional object instantiation*) Also if you go one version below i.e. Java 6 the multi-catch block `catch (InterruptedException | ExecutionException | TimeoutException e)` would split into three catch blocks (*in addition to the earlier one*) – Bond - Java Bond Feb 04 '15 at 06:05
  • Regarding 'flow control with exception' the original code you posted made a recursive call from catch block; which is not advised. catch blocks are meant to terminate execution gracefully, perform clean-up and logging; which is I posted i.e. cancel the task. You can read further [here](http://programmers.stackexchange.com/questions/189222/are-exceptions-as-control-flow-considered-a-serious-antipattern-if-so-why) and [here](http://stackoverflow.com/questions/729379/why-not-use-exceptions-as-regular-flow-of-control) (*if not already*) – Bond - Java Bond Feb 04 '15 at 06:13
  • Thank you and thank you :) About flow control, the links you provided seem to focus on readability issues and dismiss efficiency. I've been reading conflicting information about how much performance/effieciency is affected. Your link: "•Arguments for efficiency tend to be moot for modern compilers" vs ["hard for the compiler/VM to optimize because it's hard to know, at the place an exception is thrown, whether the stack trace is needed"](http://www.c2.com/cgi/wiki?DontUseExceptionsForFlowControl). There were other links I read that said similar to the latter but I cannot find them now. – RoboLam Feb 04 '15 at 18:04
  • I'm stuck with my implimentation of your suggestion. I would be very greatful if you would take a look and let me know where my mistake is. Thank you in advance. – RoboLam May 06 '15 at 15:15
  • Forgot to post link http://stackoverflow.com/questions/30064361/how-to-correctly-use-scheduledexecutorservice – RoboLam May 06 '15 at 19:55