I need to create a thread, which everyday checks whether I have to create the tasks for this user or not. I know to create and run java threads by using main(). But how to run it in web application. Seriously I searched a lot and didn't get any answer for running in web application. I have few questions regarding this.
1 How my thread will initially start and from where it will run?
2 Do I need to define my thread in any XML file ?
This is my thread
public class TaskGenerationThread implements Runnable {
#Override
public void run(){
System.out.println("callled at "+ new Date());
/*try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
/*List<Users> listOfCA = complianceUserService.getAllCA();
if(listOfCA !=null && !listOfCA.isEmpty()){
Users ca = complianceUserService.fetchUserByUserId(1).get(0);
Date currentDate = new Date();
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MONTH, 1);
calendar.set(Calendar.DATE, calendar.getActualMinimum(Calendar.DAY_OF_MONTH)); //getting first day of month
Date nextMonthFirstDay = calendar.getTime();
calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DAY_OF_MONTH)); //getting last day of month
Date nextMonthLastDay = calendar.getTime();
taskGeneratorService.generateCronJobTaskForCompanyCompliance(nextMonthFirstDay,nextMonthLastDay,ca);
}*/
}
}
I did this way. Implemented ServletContextListener and passed my Thread object. But didnt work
public class ThreadImplementation implements ServletContextListener{
ScheduledExecutorService listChecker =null;
#Override
public void contextInitialized(ServletContextEvent sce){
listChecker = Executors.newScheduledThreadPool(1);
listChecker.scheduleAtFixedRate(new TaskGenerationThread(), 01, 01, TimeUnit.SECONDS);
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
if (listChecker != null) {
listChecker.shutdownNow();
try {
listChecker.awaitTermination(60, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Any help will be highly appreciated. Thank you
Write a class that
implements ServletContextListener
override
public void contextInitialized(ServletContextEvent sce)
and kick off some scheduler from here
e.g.
listChecker = Executors.newScheduledThreadPool(1);
listChecker.scheduleAtFixedRate(filechecker, 60, 60, TimeUnit.SECONDS);
note this works for Tomcat
Your contextDestroyed should be something like
#Override
public void contextDestroyed(ServletContextEvent sce) {
log.info("Scheduler entered contextDestroyed");
if (listChecker != null) {
listChecker.shutdownNow();
log.info("waiting [60 seconds] for collector threads to finsih");
try {
listChecker.awaitTermination(60, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log.info("Scheduler finished contextDestroyed");
}
And of course you need to add it to web.xml
<listener>
<listener-class>
myPackage.Scheduler
</listener-class>
</listener>
Related
I created a schedule work with scheduleAtFixedRate, and the thread I set 2 ways to execute, 1、
Thread.sleep(10000);
Thread.sleep(200);
when I run this code, it will execute with a 2s delay, but when a==3, the thread sleep 10s, and then, there will exclude 5 thread immediately, How can I just run 1 thread but not 5?
public class Words {
private int a =0;
public void init(){
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
Date d = new Date();
SimpleDateFormat sbf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
System.out.println(sbf.format(d));
try {
if (a == 3) {
Thread.sleep(10000);
} else {
Thread.sleep(200);
}
a += 1;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, 0, 2, TimeUnit.SECONDS);
}
public static void main(String[] args) {
Words words = new Words();
words.init();
}
}
Maybe the thread will execute very long, but I don't want the scheduleAtFixedRate to execute a lot of threads like the phenomenon I've said, How can the scheduleAtFixedRate just run 1 thread? thank you
Hi this is my Cron Scheduler
public class CronListener implements ServletContextListener {
Scheduler scheduler = null;
#Override
public void contextInitialized(ServletContextEvent servletContext) {
System.out.println("Context Initialized");
try {
// Setup the Job class and the Job group
JobDetail job = newJob(CronJob.class).withIdentity("CronQuartzJob",
"Webapp").build();
// This is what I've tried as well
/*
* JobDataMap jdm = new JobDataMap(); jdm.put("targetDAO",
* targetDAO);
*/
// Create a Trigger that fires every X minutes.
Trigger trigger = newTrigger()
.withIdentity("CronQuartzJob", "Sauver")
.withSchedule(
CronScheduleBuilder.cronSchedule
("0 0/1 * 1/1 * ? *")).build();
// Setup the Job and Trigger with Scheduler & schedule jobs
scheduler = new StdSchedulerFactory().getScheduler();
scheduler.start();
scheduler.scheduleJob(job, trigger);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
#Override
public void contextDestroyed(ServletContextEvent servletContext) {
System.out.println("Context Destroyed");
try {
scheduler.shutdown();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
And here's the Cron Job itself
public class CronJob implements org.quartz.Job {
static Logger log = Logger.getLogger(CronJob.class.getName());
#Autowired
TargetDAO targetDAO;
#Override
public void execute(JobExecutionContext context)
throws JobExecutionException {
try {
targetDAO.getAllTargets();
} catch (Exception e1) {
e1.printStackTrace();
}
log.info("webapp-rest cron job started");
try {
Utils.getProcessed();
} catch (Exception e) {
e.printStackTrace();
}
}
What I'm trying to do is getting a DAO class to call some data into it and call a function through it, every few hours.
But when I call data through the DAO, it always returns empty.
What I've found is that I must map the DAO somehow, I've seen in xml-based cron jobs, but I am unable to map it in this one.
This not exactly an answer, but a workaround,
What I did was made a new class
#EnableScheduling
#Component
public class SpringCronJob {
private static Logger log = Logger.getLogger(SpringCronJob.class.getName());
#Autowired
TargetDAO targetDAO;
#Scheduled(fixedRate = 15000)
public void getPostedTargets() {
try {
log.info(targetDAO.getAllTargets());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
It doesn't need anything else, no scheduler, you just need to add it to your component scan
This is what lead me to it
http://howtodoinjava.com/spring/spring-core/4-ways-to-schedule-tasks-in-spring-3-scheduled-example/
I have a thread in my java code as given below. It is working fine in local Dev and QC environment. But some data is missing Production environment. Is there any problem in the following thread? Is there any way that i can reproduce the same?
public class MyThread implements Runnable {
private ProcessBean processBean;
public MyThread(ProcessBean processBean) {
this.processBean = processBean;
}
public void run() {
processCommand();
try {
processData(processBean);
}catch (Exception e) {
e.printStackTrace();
}
}
private void processCommand() {
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public Boolean processData(ProcessBean processBean) throws Exception{
doSomething();
}
}
In the following code processData() method will process the data. So some data is not being processed randomly giving no clue.
The calling for the thread is as follows:
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(2);
MyThread myThread = new MyThread(processBean);
scheduledThreadPool.schedule(myThread, 1, TimeUnit.SECONDS);
Please help me.
Good day to all of you .
I have a Thread as shown below , which in its while true condition , continuously checks data inside a HashSet , if it present it extracts those and does something and incase there were no symbols for 5 minutes in HashSet (here is my question how can i keep such a condition in below else block is that possible )
package com;
import java.util.HashSet;
public class Tester extends Thread
{
HashSet<String> set = new HashSet<String>();
public void run() {
while (true) {
try {
if (set.size() > 0) {
// extract those and do something
set.clear();
}
else {
// if there were no elements in set for more than 5 minutes than execute a task
// here is my question , to keep such a check is possible or not
}
Thread.sleep(2000);
} catch (Exception e) {
}
}
}
public static void main(String args[]) {
try {
Tester qT = new Tester();
qT.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
You can initialize a timestamp before your loop. Then, if set.size() > 0 is true, you update the timestamp to the current time. In the else you check whether the saved timestamp is at least 5 minutes older than the current timestamp.
You probably want something like this:
package com;
import java.util.HashSet;
import java.util.Date;
public class Tester extends Thread
{
HashSet<String> set = new HashSet<String>();
public void run() {
Date d = new Date();
while (true) {
try {
if (set.size() > 0) {
d = new Date();
set.clear();
}
else {
if(new Date().getTime() - d.getTime() > 300000){
d = new Date();
//execute your method
}
}
Thread.sleep(2000);
} catch (Exception e) {
}
}
}
public static void main(String args[]) {
try {
Tester qT = new Tester();
qT.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
First, create a timer:
Timer timer = new Timer(300000, new ActionListener() {
public void actionPerformed(ActionEvent event) {
<preform the task here>
}
});
timer.setRepeats(false);
When the thread starts, start the timer:
timer.start();
If there are items in the set:
timer.restart();
There is no need for an else, the timer takes care of that. You should check timer.isRunning in the main loop condition so the checks for set elements stop after 5 minutes.
When the thread enters run , get the SystemTime . Also get the current time in else block as shown below: Also in case we get data from hashset just compute the new system time t1
package com;
import java.util.HashSet;
public class Tester extends Thread
{
HashSet<String> set = new HashSet<String>();
public void run() {
long t1 = date.getTime();
while (true) {
try {
if (set.size() > 0) {
// extract those and do something
set.clear();
}
else {
// if there were no elements in set for more than 5 minutes than execute a task
// here is my question , to keep such a check is possible or not
long t1 = date.getTime();
if(!hashset_data_not_available)
{
t1 = date.getTime();
}
if((t2-t1)/(60*1000)>5 && if_hashset_data_not_available) {
//do something that u wanna do
{
}
Thread.sleep(2000);
} catch (Exception e) {
This question already has answers here:
How to run a background task in a servlet based web application?
(5 answers)
Closed 7 years ago.
EDIT:
The current code is the working solution, the one which does not block the application, it
incorporates the suggestion made in the approved answer.
I want a background thread to download an MS Access database continuously, while my tomcat 7 web application is running, the thread does download the database, however it seems to block my application's startup as I'm unable to access any page from the service, this is the code that I'm using:
public class DatabaseUpdater implements ServletContextListener {
private Thread thread = null;
private final Runnable updater = new Runnable() {
private boolean hasExpired(File mdbFile) throws IOException {
if (!mdbFile.exists())
return true;
Long ttl = Long.parseLong(Configuration.getValueForOS("db.http-expiration"));
Date now = new Date();
Date fileDate = new Date(mdbFile.lastModified());
return (now.getTime() - fileDate.getTime()) > ttl;
}
#Override
public void run() {
while (true) {
if (Thread.currentThread().isInterrupted())
throw new RuntimeException("Application Shutdown");
try {
String databases[] = new String[]{"database1", "database2"};
for (String database : databases) {
String fileName = database + "." + StringUtil.randomString(8) + ".mdb";
String fileLocation = Configuration.getValueForOS("db.path");
File mdbFile = new File(fileLocation, fileName);
File currentDatabaseFile = new File(fileLocation, database + ".mdb");
if (hasExpired(currentDatabaseFile)) {
URL url = new URL(Configuration.getValueForOS("db.url." + database));
InputStream in = url.openConnection().getInputStream();
OutputStream out = new FileOutputStream(mdbFile);
FileUtil.streamBridge(in, out);
FileUtil.close(in, out);
while (currentDatabaseFile.exists() && !currentDatabaseFile.delete()) ;
while (!mdbFile.renameTo(currentDatabaseFile)) ;
}
}
// Put the thread to sleep so the other threads do not starve
Thread.sleep(Long.parseLong(
Configuration.getValueForOS("db.http-expiration"));
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
};
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
this.thread = new Thread(updater);
thread.start();
}
#Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
if (this.thread.isAlive())
this.thread.interrupt();
}
}
What could be causing?
I based my implementation on this question: Background Thread for a Tomcat servlet app
Given that your code loops forever, you're probably starving all the other threads in the VM. Try sleeping the thread once in a while.