0

I have a class called "Scheduler":

package Modelo;

import java.util.ArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 *
 * @author Juan Cruz
 */
public class Scheduler implements Runnable{

    private Runnable task;
    private ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);

    public Scheduler(Runnable task, ScheduledExecutorService executorService) {
        this.task = task;
        this.executorService = executorService;
    }

    public void sesionesAbiertas() {
        Runnable beeper = new Runnable() {
            public void run() {
                    /* Code */
                }
            }
        };
        ScheduledFuture<?> beeperHandle = executorService.scheduleAtFixedRate(beeper, 10, 10, TimeUnit.SECONDS);
        executorService.schedule(new Runnable() {
            public void run() {
                beeperHandle.cancel(true);
            }
        }, 60 * 60, TimeUnit.SECONDS);
    }

    @Override
    public void run() {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }
}

The problem is that it is never executed and I don't know what to do to call it the first time, so it starts executing the code every 10 seconds (as you can see in executorService)

I think I am missing something to call you for the first time but I have read the documentation and I cannot find what is missing

EDIT: I try delete "implements Runnable" in the name of the class and deleting the last function "@override public void run()"

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Jcbreppe
  • 31
  • 5
  • On what server are you trying to deploy (e.g. Tomcat)? What other facilities besides Servlets -if any- do you have access to and are willing to use (e.g. CDI)? Do you want to use a Servlet-only solution, even if you have access to the other facilities of the previous question? – Nikos Paraskevopoulos May 30 '21 at 19:34

1 Answers1

1

Simplified example code

Here is a revamped version of your code to accomplish your goal.

Always shutdown your executor service. Otherwise its backing thread pool may run indefinitely, like a zombie ‍♂️.

System.out.println( "INFO - Running main method. " + Instant.now() );

ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();

Runnable beeper = new Runnable()
{
    public void run ( )
    {
        System.out.println( "BEEP " + Instant.now() );
    }
};
ScheduledFuture < ? > beeperScheduledFuture = ses.scheduleAtFixedRate( beeper , 3 , 10 , TimeUnit.SECONDS );

Runnable beeperKiller = new Runnable()
{
    public void run ( )
    {
        System.out.println( "Canceling beeper. " + Instant.now() );
        beeperScheduledFuture.cancel( false );
    }
};
ses.schedule( beeperKiller , 40 , TimeUnit.SECONDS );

// Let the app run a while.
System.out.println( "INFO - Sleeping main method’s thread. " + Instant.now() );
try { Thread.sleep( Duration.ofMinutes( 1 ).toMillis() ); } catch ( InterruptedException e ) { e.printStackTrace(); }
System.out.println( "INFO - Waking main method’s thread. " + Instant.now() );

// Always shutdown your executor service. 
// Otherwise its backing thread pool may run indefinitely, like a zombie ‍♂️.
ses.shutdown();
try { ses.awaitTermination( 2 , TimeUnit.MINUTES ); } catch ( InterruptedException e ) { e.printStackTrace(); }

System.out.println( "INFO - Done running main method. Scheduled executor service is shutdown at this point. " + Instant.now() );

When run.

INFO - Running main method. 2021-05-30T22:08:38.325323Z
INFO - Sleeping main method’s thread. 2021-05-30T22:08:38.350518Z
BEEP 2021-05-30T22:08:41.354945Z
BEEP 2021-05-30T22:08:51.354414Z
BEEP 2021-05-30T22:09:01.353793Z
BEEP 2021-05-30T22:09:11.354173Z
Canceling beeper. 2021-05-30T22:09:18.354231Z
INFO - Waking main method’s thread. 2021-05-30T22:09:38.355860Z
INFO - Done running main method. Scheduled executor service is shutdown at this point. 2021-05-30T22:09:38.356450Z

Jakarta Servlets with background threads

You tagged your Question with servlets but did not explain. Running this code within a Jakarta Servlet environment raises a host of other issues. I'll just give a few quick points to explore.

I have written on using background threads via executor services with Servlets multiple times. And others have written as well. Search to learn more.

ServletContextListener

The Jakarta Servlet spec defines the lifecycle of a web app. By web app, I mean one or more Servlets working together while sharing a “Context”.

The ServletContextListener interface provides hooks for you to run code when your web app starts (before the first request is handled) and when your web app ends (after the last request is handled). You can write a class implementing that interface, annotated with @WebListener to automatically be detected, loaded, and executed by your Servlet container such as Apache Tomcat, Eclipse Jetty, etc.

Writing such a class to implement ServletContextListener is a good place to set up and shut down your executor service.

Jakarta Concurrency spec

If you are using a fully equipped Jakarta EE server such as GlassFish, Payara, WildFly, JBoss, OpenLiberty, WebSphere, WebLogic, etc., you can use Jakarta Concurrency to automate much of what I described above. A few annotations can replace much code.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • Very thanks! but the problem is that it does not run because (I think) it is a class like any other (I have like 15 classes) and it cannot be run even with these changes. – Jcbreppe May 31 '21 at 02:14
  • It is a web application in which I have models, I have servlets, but I don't know how to execute this class as soon as the website starts, do you have any idea how to do it? – Jcbreppe May 31 '21 at 02:15
  • some like main class – Jcbreppe May 31 '21 at 02:22
  • @Jcbreppe Yes, you had kind of a screwy setup with your classes, which is understandable given how confusing concurrency is. So I tried to simplify matters so you can see all the moving parts in motion. Regarding servlets, I expanded the last section. – Basil Bourque May 31 '21 at 07:09
  • Thanks for your knowledge, im reading this now, and i try again – Jcbreppe Jun 01 '21 at 21:16
  • Yaaaaas, very thanks, at now its working! My greetings from Argentina! A last question, really I want the process to ALWAYS run every 15 minutes, it is a check of a state in the BD, If I leave it running into the script in this way, I will generate a problem? That is, without putting a stop – Jcbreppe Jun 01 '21 at 22:15
  • @Jcbreppe ***Always* shut down your executor service**. Otherwise the backing pool of threads may continue indefinitely, even after your web app ends, like a zombie ‍♂️. The `ServletContextListener` gives hooks for both start and end of your web app. That’s a good place to launch and shutdown your executor service. And, again, if using a Jakarta EE server that supports *Jakarta Concurrency* spec, much of this is automated for you. – Basil Bourque Jun 01 '21 at 22:38