fix scheduled executor services thread leak, update to Gradle 4.6-rc-1
This commit is contained in:
parent
1db95358c5
commit
00150abbb3
10 changed files with 77 additions and 48 deletions
19
build.gradle
19
build.gradle
|
@ -1,13 +1,9 @@
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id "org.sonarqube" version "2.2"
|
id "org.sonarqube" version "2.6.1"
|
||||||
id "org.ajoberstar.github-pages" version "1.6.0-rc.1"
|
id "io.codearte.nexus-staging" version "0.11.0"
|
||||||
id "org.xbib.gradle.plugin.jbake" version "1.1.0"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
group = 'org.xbib'
|
|
||||||
version = '1.0.0'
|
|
||||||
|
|
||||||
printf "Host: %s\nOS: %s %s %s\nJVM: %s %s %s %s\nGroovy: %s\nGradle: %s\n" +
|
printf "Host: %s\nOS: %s %s %s\nJVM: %s %s %s %s\nGroovy: %s\nGradle: %s\n" +
|
||||||
"Build: group: ${project.group} name: ${project.name} version: ${project.version}\n",
|
"Build: group: ${project.group} name: ${project.name} version: ${project.version}\n",
|
||||||
InetAddress.getLocalHost(),
|
InetAddress.getLocalHost(),
|
||||||
|
@ -24,10 +20,6 @@ printf "Host: %s\nOS: %s %s %s\nJVM: %s %s %s %s\nGroovy: %s\nGradle: %s\n" +
|
||||||
apply plugin: 'java'
|
apply plugin: 'java'
|
||||||
apply plugin: 'maven'
|
apply plugin: 'maven'
|
||||||
apply plugin: 'signing'
|
apply plugin: 'signing'
|
||||||
apply plugin: 'findbugs'
|
|
||||||
apply plugin: 'pmd'
|
|
||||||
apply plugin: 'checkstyle'
|
|
||||||
apply plugin: "jacoco"
|
|
||||||
|
|
||||||
apply from: 'gradle/ext.gradle'
|
apply from: 'gradle/ext.gradle'
|
||||||
|
|
||||||
|
@ -37,9 +29,9 @@ configurations {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
testCompile "junit:junit:4.12"
|
testCompile "junit:junit:4.12"
|
||||||
testCompile "org.apache.logging.log4j:log4j-core:2.7"
|
testCompile "org.apache.logging.log4j:log4j-core:2.10.0"
|
||||||
testCompile "org.apache.logging.log4j:log4j-slf4j-impl:2.7"
|
testCompile "org.apache.logging.log4j:log4j-slf4j-impl:2.10.0"
|
||||||
wagon 'org.apache.maven.wagon:wagon-ssh-external:2.10'
|
wagon 'org.apache.maven.wagon:wagon-ssh:3.0.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceCompatibility = 1.8
|
sourceCompatibility = 1.8
|
||||||
|
@ -72,4 +64,3 @@ if (project.hasProperty('signing.keyId')) {
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: 'gradle/publish.gradle'
|
apply from: 'gradle/publish.gradle'
|
||||||
apply from: 'gradle/sonarqube.gradle'
|
|
||||||
|
|
6
gradle.properties
Normal file
6
gradle.properties
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
group = org.xbib
|
||||||
|
name = metrics
|
||||||
|
version = 1.1.0
|
||||||
|
|
||||||
|
junit.version = 4.12
|
||||||
|
wagon.version = 3.0.0
|
|
@ -1,5 +1,5 @@
|
||||||
ext {
|
ext {
|
||||||
user = 'xbib'
|
user = 'jprante'
|
||||||
name = 'metrics'
|
name = 'metrics'
|
||||||
description = 'A stripped-down and modified version of Coda Hale Metrics'
|
description = 'A stripped-down and modified version of Coda Hale Metrics'
|
||||||
scmUrl = 'https://github.com/' + user + '/' + name
|
scmUrl = 'https://github.com/' + user + '/' + name
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
|
|
||||||
task xbibUpload(type: Upload) {
|
task xbibUpload(type: Upload) {
|
||||||
|
group = 'publish'
|
||||||
configuration = configurations.archives
|
configuration = configurations.archives
|
||||||
uploadDescriptor = true
|
uploadDescriptor = true
|
||||||
repositories {
|
repositories {
|
||||||
if (project.hasProperty("xbibUsername")) {
|
if (project.hasProperty("xbibUsername")) {
|
||||||
mavenDeployer {
|
mavenDeployer {
|
||||||
configuration = configurations.wagon
|
configuration = configurations.wagon
|
||||||
repository(url: 'scpexe://xbib.org/repository') {
|
repository(url: project.property('xbibUrl')) {
|
||||||
authentication(userName: xbibUsername, privateKey: xbibPrivateKey)
|
authentication(userName: xbibUsername, privateKey: xbibPrivateKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +16,7 @@ task xbibUpload(type: Upload) {
|
||||||
}
|
}
|
||||||
|
|
||||||
task sonaTypeUpload(type: Upload) {
|
task sonaTypeUpload(type: Upload) {
|
||||||
|
group = 'publish'
|
||||||
configuration = configurations.archives
|
configuration = configurations.archives
|
||||||
uploadDescriptor = true
|
uploadDescriptor = true
|
||||||
repositories {
|
repositories {
|
||||||
|
@ -64,3 +66,7 @@ task sonaTypeUpload(type: Upload) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nexusStaging {
|
||||||
|
packageGroup = "org.xbib"
|
||||||
|
}
|
||||||
|
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
3
gradle/wrapper/gradle-wrapper.properties
vendored
3
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,5 @@
|
||||||
#Tue Nov 01 15:47:24 CET 2016
|
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-rc-1-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-3.1-bin.zip
|
|
||||||
|
|
23
gradlew
vendored
23
gradlew
vendored
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
##
|
##
|
||||||
|
@ -33,11 +33,11 @@ DEFAULT_JVM_OPTS=""
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD="maximum"
|
MAX_FD="maximum"
|
||||||
|
|
||||||
warn ( ) {
|
warn () {
|
||||||
echo "$*"
|
echo "$*"
|
||||||
}
|
}
|
||||||
|
|
||||||
die ( ) {
|
die () {
|
||||||
echo
|
echo
|
||||||
echo "$*"
|
echo "$*"
|
||||||
echo
|
echo
|
||||||
|
@ -154,16 +154,19 @@ if $cygwin ; then
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
# Escape application args
|
||||||
function splitJvmOpts() {
|
save () {
|
||||||
JVM_OPTS=("$@")
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
}
|
}
|
||||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
APP_ARGS=$(save "$@")
|
||||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
|
||||||
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||||
if [[ "$(uname)" == "Darwin" ]] && [[ "$HOME" == "$PWD" ]]; then
|
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
exec "$JAVACMD" "$@"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package org.xbib.metrics;
|
package org.xbib.metrics;
|
||||||
|
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
@ -15,37 +15,51 @@ import java.util.concurrent.atomic.LongAdder;
|
||||||
public class Meter implements Metered {
|
public class Meter implements Metered {
|
||||||
private static final long TICK_INTERVAL = TimeUnit.SECONDS.toNanos(5);
|
private static final long TICK_INTERVAL = TimeUnit.SECONDS.toNanos(5);
|
||||||
|
|
||||||
private final ExpWeightedMovingAverage m1Rate = ExpWeightedMovingAverage.oneMinuteEWMA();
|
private final ScheduledExecutorService executorService;
|
||||||
private final ExpWeightedMovingAverage m5Rate = ExpWeightedMovingAverage.fiveMinuteEWMA();
|
|
||||||
private final ExpWeightedMovingAverage m15Rate = ExpWeightedMovingAverage.fifteenMinuteEWMA();
|
private final ExpWeightedMovingAverage m1Rate;
|
||||||
|
|
||||||
|
private final ExpWeightedMovingAverage m5Rate;
|
||||||
|
|
||||||
|
private final ExpWeightedMovingAverage m15Rate;
|
||||||
|
|
||||||
|
private final LongAdder count;
|
||||||
|
|
||||||
private final LongAdder count = new LongAdder();
|
|
||||||
private final AtomicLong lastTick;
|
private final AtomicLong lastTick;
|
||||||
|
|
||||||
private final Clock clock;
|
private final Clock clock;
|
||||||
|
|
||||||
private long startedAt;
|
private long startedAt;
|
||||||
|
|
||||||
private ScheduledFuture<?> future;
|
private ScheduledFuture<?> future;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link Meter}.
|
* Creates a new {@link Meter}.
|
||||||
|
* @param executorService the executor service
|
||||||
*/
|
*/
|
||||||
public Meter() {
|
public Meter(ScheduledExecutorService executorService) {
|
||||||
this(Clock.defaultClock());
|
this(executorService, Clock.defaultClock());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link Meter}.
|
* Creates a new {@link Meter}.
|
||||||
*
|
*
|
||||||
|
* @param executorService the executor service
|
||||||
* @param clock the clock to use for the meter ticks
|
* @param clock the clock to use for the meter ticks
|
||||||
*/
|
*/
|
||||||
public Meter(Clock clock) {
|
public Meter(ScheduledExecutorService executorService, Clock clock) {
|
||||||
|
this.executorService = executorService;
|
||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
this.startedAt = this.clock.getTick();
|
|
||||||
this.lastTick = new AtomicLong(startedAt);
|
this.lastTick = new AtomicLong(startedAt);
|
||||||
|
m1Rate = ExpWeightedMovingAverage.oneMinuteEWMA();
|
||||||
|
m5Rate = ExpWeightedMovingAverage.fiveMinuteEWMA();
|
||||||
|
m15Rate = ExpWeightedMovingAverage.fifteenMinuteEWMA();
|
||||||
|
count = new LongAdder();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void spawn(long intervalSeconds) {
|
public void start(long intervalSeconds) {
|
||||||
this.future = Executors.newScheduledThreadPool(1)
|
this.startedAt = this.clock.getTick();
|
||||||
|
this.future = executorService
|
||||||
.scheduleAtFixedRate(this::tickIfNecessary, intervalSeconds, intervalSeconds, TimeUnit.SECONDS);
|
.scheduleAtFixedRate(this::tickIfNecessary, intervalSeconds, intervalSeconds, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +67,11 @@ public class Meter implements Metered {
|
||||||
future.cancel(false);
|
future.cancel(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void shutdown() {
|
||||||
|
stop();
|
||||||
|
executorService.shutdownNow();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark the occurrence of an event.
|
* Mark the occurrence of an event.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -10,6 +10,7 @@ import java.util.TreeSet;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
@ -486,7 +487,7 @@ public class MetricRegistry implements MetricSet {
|
||||||
MetricBuilder<Meter> METERS = new MetricBuilder<Meter>() {
|
MetricBuilder<Meter> METERS = new MetricBuilder<Meter>() {
|
||||||
@Override
|
@Override
|
||||||
public Meter newMetric() {
|
public Meter newMetric() {
|
||||||
return new Meter();
|
return new Meter(Executors.newSingleThreadScheduledExecutor());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -498,7 +499,7 @@ public class MetricRegistry implements MetricSet {
|
||||||
MetricBuilder<Sampler> TIMERS = new MetricBuilder<Sampler>() {
|
MetricBuilder<Sampler> TIMERS = new MetricBuilder<Sampler>() {
|
||||||
@Override
|
@Override
|
||||||
public Sampler newMetric() {
|
public Sampler newMetric() {
|
||||||
return new Sampler();
|
return new Sampler(Executors.newSingleThreadScheduledExecutor());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.xbib.metrics;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -17,18 +18,20 @@ public class Sampler implements Metered, Sampling {
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link Sampler} using an {@link ExponentiallyDecayingReservoir} and the default
|
* Creates a new {@link Sampler} using an {@link ExponentiallyDecayingReservoir} and the default
|
||||||
* {@link Clock}.
|
* {@link Clock}.
|
||||||
|
* @param executorService the executor service
|
||||||
*/
|
*/
|
||||||
public Sampler() {
|
public Sampler(ScheduledExecutorService executorService) {
|
||||||
this(new ExponentiallyDecayingReservoir());
|
this(new ExponentiallyDecayingReservoir(), executorService);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link Sampler} that uses the given {@link Reservoir}.
|
* Creates a new {@link Sampler} that uses the given {@link Reservoir}.
|
||||||
*
|
*
|
||||||
* @param reservoir the {@link Reservoir} implementation the sampler should use
|
* @param reservoir the {@link Reservoir} implementation the sampler should use
|
||||||
|
* @param executorService the executor service
|
||||||
*/
|
*/
|
||||||
public Sampler(Reservoir reservoir) {
|
public Sampler(Reservoir reservoir, ScheduledExecutorService executorService) {
|
||||||
this(reservoir, Clock.defaultClock());
|
this(reservoir, Clock.defaultClock(), executorService);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,11 +39,12 @@ public class Sampler implements Metered, Sampling {
|
||||||
*
|
*
|
||||||
* @param reservoir the {@link Reservoir} implementation the sampler should use
|
* @param reservoir the {@link Reservoir} implementation the sampler should use
|
||||||
* @param clock the {@link Clock} implementation the sampler should use
|
* @param clock the {@link Clock} implementation the sampler should use
|
||||||
|
* @param executorService the executor service
|
||||||
*/
|
*/
|
||||||
public Sampler(Reservoir reservoir, Clock clock) {
|
public Sampler(Reservoir reservoir, Clock clock, ScheduledExecutorService executorService) {
|
||||||
this.meter = new Meter(clock);
|
|
||||||
this.clock = clock;
|
|
||||||
this.histogram = new Histogram(reservoir);
|
this.histogram = new Histogram(reservoir);
|
||||||
|
this.clock = clock;
|
||||||
|
this.meter = new Meter(executorService, clock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue