You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by th...@apache.org on 2014/12/07 03:29:02 UTC
[04/45] tapestry-5 git commit: TAP5-2406: Use a single ReentrantLock
for the PeriodicExecutor and its jobs
TAP5-2406: Use a single ReentrantLock for the PeriodicExecutor and its jobs
Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/32571619
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/32571619
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/32571619
Branch: refs/heads/beanmodel-split
Commit: 3257161990f639eabb60ce8729e3c1244823609a
Parents: 57a8d25
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Fri Oct 24 13:59:37 2014 -0700
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Fri Oct 24 13:59:37 2014 -0700
----------------------------------------------------------------------
.../services/cron/PeriodicExecutorImpl.java | 181 +++++++++++++------
1 file changed, 121 insertions(+), 60 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/32571619/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/cron/PeriodicExecutorImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/cron/PeriodicExecutorImpl.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/cron/PeriodicExecutorImpl.java
index abfcde9..cf3c717 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/cron/PeriodicExecutorImpl.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/cron/PeriodicExecutorImpl.java
@@ -1,5 +1,3 @@
-// Copyright 2011 The Apache Software Foundation
-//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
@@ -26,6 +24,8 @@ import org.slf4j.Logger;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
public class PeriodicExecutorImpl implements PeriodicExecutor, Runnable
{
@@ -33,18 +33,19 @@ public class PeriodicExecutorImpl implements PeriodicExecutor, Runnable
private final Logger logger;
- // Synchronized by this
+ // Synchronized by jobLock
private final List<Job> jobs = CollectionFactory.newList();
private final Thread thread = new Thread(this, "Tapestry PeriodicExecutor");
- // Synchronized by this. Set when the registry is shutdown.
- private boolean shutdown;
+ private transient boolean shutdown;
private static final long FIVE_MINUTES = 5 * 60 * 1000;
private final AtomicInteger jobIdAllocator = new AtomicInteger();
+ private final Lock jobLock = new ReentrantLock();
+
private class Job implements PeriodicJob, Invokable<Void>
{
final int jobId = jobIdAllocator.incrementAndGet();
@@ -74,43 +75,71 @@ public class PeriodicExecutorImpl implements PeriodicExecutor, Runnable
return name;
}
- public synchronized long getNextExecution()
+ public long getNextExecution()
{
- return nextExecution;
+ try
+ {
+ jobLock.lock();
+ return nextExecution;
+ } finally
+ {
+ jobLock.unlock();
+ }
}
@Override
- public synchronized boolean isExecuting()
+ public boolean isExecuting()
{
- return executing;
+ try
+ {
+ jobLock.lock();
+ return executing;
+ } finally
+ {
+ jobLock.unlock();
+ }
}
@Override
- public synchronized boolean isCanceled()
+ public boolean isCanceled()
{
- return canceled;
+ try
+ {
+ jobLock.lock();
+ return canceled;
+ } finally
+ {
+ jobLock.unlock();
+ }
}
@Override
- public synchronized void cancel()
+ public void cancel()
{
- canceled = true;
+ try
+ {
+ jobLock.lock();
+
+ canceled = true;
+
+ if (!executing)
+ {
+ removeJob(this);
+ }
- if (!executing)
+ // Otherwise, it will be caught when the job finishes execution.
+ } finally
{
- removeJob(this);
+ jobLock.unlock();
}
-
- // Otherwise, it will be caught when the job finishes execution.
}
@Override
- public synchronized String toString()
+ public String toString()
{
StringBuilder builder = new StringBuilder("PeriodicJob[#").append(jobId);
-
builder.append(", (").append(name).append(")");
if (executing)
@@ -133,17 +162,24 @@ public class PeriodicExecutorImpl implements PeriodicExecutor, Runnable
* Starts execution of the job; this sets the executing flag, calculates the next execution time,
* and uses the ParallelExecutor to run the job.
*/
- synchronized void start()
+ void start()
{
- executing = true;
+ try
+ {
+ jobLock.lock();
+ executing = true;
- // This is a bit naive; it assumes there will not be a delay waiting to execute. There's a lot of options
- // here, such as basing the next execution on the actual start time, or event actual completion time, or allowing
- // overlapping executions of the Job on a more rigid schedule. Use Quartz.
+ // This is a bit naive; it assumes there will not be a delay waiting to execute. There's a lot of options
+ // here, such as basing the next execution on the actual start time, or event actual completion time, or allowing
+ // overlapping executions of the Job on a more rigid schedule. Use Quartz.
- nextExecution = schedule.nextExecution(nextExecution);
+ nextExecution = schedule.nextExecution(nextExecution);
- parallelExecutor.invoke(this);
+ parallelExecutor.invoke(this);
+ } finally
+ {
+ jobLock.unlock();
+ }
if (logger.isTraceEnabled())
{
@@ -151,22 +187,28 @@ public class PeriodicExecutorImpl implements PeriodicExecutor, Runnable
}
}
- synchronized void cleanupAfterExecution()
+ void cleanupAfterExecution()
{
- if (logger.isTraceEnabled())
+ try
{
- logger.trace(this + " execution complete");
- }
+ if (logger.isTraceEnabled())
+ {
+ logger.trace(this + " execution complete");
+ }
- executing = false;
+ executing = false;
- if (canceled)
- {
- removeJob(this);
- } else
+ if (canceled)
+ {
+ removeJob(this);
+ } else
+ {
+ // Again, naive but necessary.
+ thread.interrupt();
+ }
+ } finally
{
- // Again, naive but necessary.
- thread.interrupt();
+ jobLock.unlock();
}
}
@@ -188,6 +230,7 @@ public class PeriodicExecutorImpl implements PeriodicExecutor, Runnable
return null;
}
+
}
public PeriodicExecutorImpl(ParallelExecutor parallelExecutor, Logger logger)
@@ -212,19 +255,26 @@ public class PeriodicExecutorImpl implements PeriodicExecutor, Runnable
}
- synchronized void removeJob(Job job)
+ void removeJob(Job job)
{
if (logger.isDebugEnabled())
{
logger.debug("Removing " + job);
}
- jobs.remove(job);
+ try
+ {
+ jobLock.lock();
+ jobs.remove(job);
+ } finally
+ {
+ jobLock.unlock();
+ }
}
@Override
- public synchronized PeriodicJob addJob(Schedule schedule, String name, Runnable job)
+ public PeriodicJob addJob(Schedule schedule, String name, Runnable job)
{
assert schedule != null;
assert name != null;
@@ -232,7 +282,15 @@ public class PeriodicExecutorImpl implements PeriodicExecutor, Runnable
Job periodicJob = new Job(schedule, name, job);
- jobs.add(periodicJob);
+ try
+ {
+ jobLock.lock();
+
+ jobs.add(periodicJob);
+ } finally
+ {
+ jobLock.unlock();
+ }
if (logger.isDebugEnabled())
{
@@ -252,7 +310,7 @@ public class PeriodicExecutorImpl implements PeriodicExecutor, Runnable
@Override
public void run()
{
- while (!isShutdown())
+ while (!shutdown)
{
long nextExecution = executeCurrentBatch();
@@ -280,12 +338,7 @@ public class PeriodicExecutorImpl implements PeriodicExecutor, Runnable
}
}
- private synchronized boolean isShutdown()
- {
- return shutdown;
- }
-
- private synchronized void registryDidShutdown()
+ private void registryDidShutdown()
{
shutdown = true;
@@ -297,27 +350,35 @@ public class PeriodicExecutorImpl implements PeriodicExecutor, Runnable
*
* @return the next execution time (from the non-executing job that is scheduled earliest for execution).
*/
- private synchronized long executeCurrentBatch()
+ private long executeCurrentBatch()
{
long now = System.currentTimeMillis();
long nextExecution = now + FIVE_MINUTES;
- for (Job job : jobs)
+ try
{
- if (job.isExecuting())
+ jobLock.lock();
+
+ for (Job job : jobs)
{
- continue;
- }
+ if (job.isExecuting())
+ {
+ continue;
+ }
- long jobNextExecution = job.getNextExecution();
+ long jobNextExecution = job.getNextExecution();
- if (jobNextExecution <= now)
- {
- job.start();
- } else
- {
- nextExecution = Math.min(nextExecution, jobNextExecution);
+ if (jobNextExecution <= now)
+ {
+ job.start();
+ } else
+ {
+ nextExecution = Math.min(nextExecution, jobNextExecution);
+ }
}
+ } finally
+ {
+ jobLock.unlock();
}
return nextExecution;