假设你想要一个运行计数,而不仅仅是最后的总数,我会使用ReentrantLock来处理更新,并使用Callables和Futures而不是Runnable来处理http请求。
通常,最好避免显式同步,并尽可能依赖java.util.concurrent。
下面是在Java 6/7和Java示例解决方案8.
爪哇6/7
public class TestMainJdk7 {
public static void main(final String... args) throws Exception {
final TestRun testRun = new TestRun("http://www.google.com/search?q=java", "Chrome", 5, 5, 100000L);
final TestResults testResults = testRun.execute();
// Uncomment and add Apache commons-math to report quantiles, mean, min, max, standard deviation
// for (int quantile = 5; quantile <= 100; quantile += 5) {
// System.out.println(quantile + ": " + testResults.rawDescriptiveStatistics.getPercentile(quantile));
// }
// System.out.println("mean: " + testResults.rawDescriptiveStatistics.getMean());
// System.out.println("min: " + testResults.rawDescriptiveStatistics.getMin());
// System.out.println("max: " + testResults.rawDescriptiveStatistics.getMax());
// System.out.println("standard deviation: " + testResults.rawDescriptiveStatistics.getStandardDeviation());
}
public static class TestResults {
private final double[] rawDurations;
public final TestRun testRun;
public final List<TimedHttpRequestResult> timedHttpRequestResults;
// Uncomment and add Apache commons-math to report quantiles, mean, min, max, standard deviation
// public final org.apache.commons.math.stat.descriptive.DescriptiveStatistics rawDescriptiveStatistics;
public TestResults(final TestRun testRun, final List<TimedHttpRequestResult> timedHttpRequestResults) {
this.testRun = testRun;
this.timedHttpRequestResults = timedHttpRequestResults;
final List<Long> successfulDurations = new ArrayList<Long>();
for (final TimedHttpRequestResult timedHttpRequestResult : timedHttpRequestResults) {
if (timedHttpRequestResult.isSuccess()) {
successfulDurations.add(timedHttpRequestResult.duration);
}
}
this.rawDurations = new double[successfulDurations.size()];
for (int i = 0; i < successfulDurations.size(); i++) {
this.rawDurations[i] = successfulDurations.get(i);
}
// Uncomment and add Apache commons-math to report quantiles, mean, min, max, standard deviation
// this.rawDescriptiveStatistics = new org.apache.commons.math.stat.descriptive.DescriptiveStatistics(
// this.rawDurations);
}
}
public static class TestRun {
public final String urlString;
public final String userAgentString;
public final int threadNumber;
public final int requestNumber;
public final long timeoutInMillis;
private long totalDurationSoFar;
private int totalRunSoFar;
private int totalSuccessfulSoFar;
private final ReentrantLock lock = new ReentrantLock();
public TestRun(final String urlString, final String userAgentString, final int threadNumber,
final int requestNumber, final long timeoutInMillis) {
this.urlString = urlString;
this.threadNumber = threadNumber;
this.requestNumber = requestNumber;
this.userAgentString = userAgentString;
this.timeoutInMillis = timeoutInMillis;
}
public TestRunStatus updateCounts(final long duration, final int responseCode) {
this.lock.lock();
try {
this.totalDurationSoFar = this.totalDurationSoFar + duration;
this.totalRunSoFar++;
if (responseCode == HttpURLConnection.HTTP_OK) {
this.totalSuccessfulSoFar++;
}
return this.currentStatus();
} finally {
this.lock.unlock();
}
}
public TestRunStatus currentStatus() {
return new TestRunStatus(this.totalDurationSoFar, this.totalRunSoFar, this.totalSuccessfulSoFar);
}
public TestResults execute() throws InterruptedException {
final ExecutorService executor = Executors.newFixedThreadPool(this.threadNumber);
final Map<TimedHttpRequest, Future<TimedHttpRequestResult>> timedHttpRequestFuturesByRequest = new HashMap<TimedHttpRequest, Future<TimedHttpRequestResult>>();
for (int i = 0; i < this.requestNumber; i++) {
final TimedHttpRequest timedHttpRequest = new TimedHttpRequest(this);
timedHttpRequestFuturesByRequest.put(timedHttpRequest, executor.submit(timedHttpRequest));
}
final List<TimedHttpRequestResult> timedHttpRequestResults = new ArrayList<TimedHttpRequestResult>();
for (final Map.Entry<TimedHttpRequest, Future<TimedHttpRequestResult>> timedHttpRequestFuture : timedHttpRequestFuturesByRequest.entrySet()) {
final TimedHttpRequest timedHttpRequest = timedHttpRequestFuture.getKey();
try {
timedHttpRequestResults.add(timedHttpRequestFuture.getValue()
.get(this.timeoutInMillis, TimeUnit.MILLISECONDS));
} catch (final Exception e) {
timedHttpRequestResults.add(new TimedHttpRequestResult(timedHttpRequest, e,
this.updateCounts(0, -1)));
}
}
executor.shutdown();
return new TestResults(this, timedHttpRequestResults);
}
}
public static class TestRunStatus {
public final long totalDurationSoFar;
public final int totalRunSoFar;
public final int totalSuccessfulSoFar;
TestRunStatus(final long totalDurationSoFar, final int totalRunSoFar, final int totalSuccessfulSoFar) {
this.totalDurationSoFar = totalDurationSoFar;
this.totalRunSoFar = totalRunSoFar;
this.totalSuccessfulSoFar = totalSuccessfulSoFar;
}
}
public static class TimedHttpRequestResult {
//@formatter:off
public static final String TO_STRING_FORMAT = "\nSending 'GET' request to URL : %s"
+ "\nResponse Code : %s"
+ "\nResponse time: %s"
+ "\n---- Total time for all request = %s milliseconds"
+ "\n---- Total count of request = %s"
+ "\n---- Count of success request = %s";
//@formatter:on
public final TimedHttpRequest timedHttpRequest;
public final long duration;
public final int responseCode;
public final Exception exception;
public final TestRunStatus testRunStatus;
public TimedHttpRequestResult(final TimedHttpRequest timedHttpRequest, final long duration,
final int responseCode, final TestRunStatus testRunStatus) {
this.timedHttpRequest = timedHttpRequest;
this.duration = duration;
this.responseCode = responseCode;
this.testRunStatus = testRunStatus;
this.exception = null;
}
public TimedHttpRequestResult(final TimedHttpRequest timedHttpRequest, final Exception exception,
final TestRunStatus testRunStatus) {
this.timedHttpRequest = timedHttpRequest;
this.duration = -1L;
this.responseCode = -1;
this.testRunStatus = testRunStatus;
this.exception = exception;
}
boolean isSuccess() {
return this.responseCode == HttpURLConnection.HTTP_OK;
}
@Override
public String toString() {
return String.format(TO_STRING_FORMAT, this.timedHttpRequest.testRun.urlString, this.responseCode,
this.duration, this.testRunStatus.totalDurationSoFar, this.testRunStatus.totalRunSoFar,
this.testRunStatus.totalSuccessfulSoFar);
}
}
public static class TimedHttpRequest implements Callable<TimedHttpRequestResult> {
public final TestRun testRun;
public TimedHttpRequest(final TestRun testRun) {
this.testRun = testRun;
}
@Override
public TimedHttpRequestResult call() throws Exception {
final URL url = new URL(this.testRun.urlString);
final HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setRequestProperty("User-Agent", this.testRun.userAgentString);
final long startTime = System.nanoTime();
final int responseCode = httpURLConnection.getResponseCode();
final long endTime = System.nanoTime();
httpURLConnection.disconnect();
final long duration = TimeUnit.NANOSECONDS.toMillis(endTime - startTime);
final TimedHttpRequestResult timedHttpRequestResult = new TimedHttpRequestResult(this, duration,
responseCode, this.testRun.updateCounts(duration, responseCode));
System.out.println(timedHttpRequestResult);
return timedHttpRequestResult;
}
}
}
爪哇8
public class TestMainJdk8 {
public static void main(final String... args) throws Exception {
final TestRun testRun = new TestMainJdk8.TestRun("http://www.google.com/search?q=java", "Chrome", 5, 5,
100000L);
final TestResults testResults = testRun.execute();
// Uncomment and add Apache commons-math to report quantiles, mean, min, max, standard deviation
// for (int quantile = 5; quantile <= 100; quantile += 5) {
// System.out.println(quantile + ": " + testResults.rawDescriptiveStatistics.getPercentile(quantile));
// }
// System.out.println("mean: " + testResults.rawDescriptiveStatistics.getMean());
// System.out.println("min: " + testResults.rawDescriptiveStatistics.getMin());
// System.out.println("max: " + testResults.rawDescriptiveStatistics.getMax());
// System.out.println("standard deviation: " + testResults.rawDescriptiveStatistics.getStandardDeviation());
}
public static class TestResults {
private final double[] rawDurations;
public final TestRun testRun;
public final List<TimedHttpRequestResult> timedHttpRequestResults;
// Uncomment to report quantiles, mean, min, max, standard deviation
// public final org.apache.commons.math.stat.descriptive.DescriptiveStatistics rawDescriptiveStatistics;
public TestResults(final TestRun testRun, final List<TimedHttpRequestResult> timedHttpRequestResults) {
this.testRun = testRun;
this.timedHttpRequestResults = timedHttpRequestResults;
this.rawDurations = timedHttpRequestResults.stream()
.filter(TimedHttpRequestResult::isSuccess)
.mapToDouble(timedHttpRequestResult -> timedHttpRequestResult.duration)
.toArray();
// Uncomment and add Apache commons-math to report quantiles, mean, min, max, standard deviation
// this.rawDescriptiveStatistics = new org.apache.commons.math.stat.descriptive.DescriptiveStatistics(
// this.rawDurations);
}
}
public static class TestRun {
public final String urlString;
public final String userAgentString;
public final int threadNumber;
public final int requestNumber;
public final long timeoutInMillis;
private long totalDurationSoFar;
private int totalRunSoFar;
private int totalSuccessfulSoFar;
private final ReentrantLock lock = new ReentrantLock();
public TestRun(final String urlString, final String userAgentString, final int threadNumber,
final int requestNumber, final long timeoutInMillis) {
this.urlString = urlString;
this.threadNumber = threadNumber;
this.requestNumber = requestNumber;
this.userAgentString = userAgentString;
this.timeoutInMillis = timeoutInMillis;
}
public TestRunStatus updateCounts(final long duration, final int responseCode) {
this.lock.lock();
try {
this.totalDurationSoFar = this.totalDurationSoFar + duration;
this.totalRunSoFar++;
if (responseCode == HttpURLConnection.HTTP_OK) {
this.totalSuccessfulSoFar++;
}
return this.currentStatus();
} finally {
this.lock.unlock();
}
}
public TestRunStatus currentStatus() {
return new TestRunStatus(this.totalDurationSoFar, this.totalRunSoFar, this.totalSuccessfulSoFar);
}
public TestResults execute() throws InterruptedException {
final ExecutorService executor = Executors.newFixedThreadPool(this.threadNumber);
final Map<TimedHttpRequest, Future<TimedHttpRequestResult>> timedHttpRequestFuturesByRequest = IntStream.range(
1, this.requestNumber)
.mapToObj(index -> new TimedHttpRequest(this))
.collect(Collectors.toMap(Function.identity(), timedHttpRequest -> executor.submit(timedHttpRequest)));
final List<TimedHttpRequestResult> timedHttpRequestResults = timedHttpRequestFuturesByRequest.entrySet()
.stream()
.map(entry -> {
final TimedHttpRequest timedHttpRequest = entry.getKey();
try {
return entry.getValue()
.get(this.timeoutInMillis, TimeUnit.MILLISECONDS);
} catch (final Exception e) {
return new TimedHttpRequestResult(timedHttpRequest, e, this.updateCounts(0, -1));
}
})
.collect(Collectors.toList());
executor.shutdown();
return new TestResults(this, timedHttpRequestResults);
}
}
public static class TestRunStatus {
public final long totalDurationSoFar;
public final int totalRunSoFar;
public final int totalSuccessfulSoFar;
TestRunStatus(final long totalDurationSoFar, final int totalRunSoFar, final int totalSuccessfulSoFar) {
this.totalDurationSoFar = totalDurationSoFar;
this.totalRunSoFar = totalRunSoFar;
this.totalSuccessfulSoFar = totalSuccessfulSoFar;
}
}
public static class TimedHttpRequestResult {
//@formatter:off
public static final String TO_STRING_FORMAT = "\nSending 'GET' request to URL : %s"
+ "\nResponse Code : %s"
+ "\nResponse time: %s"
+ "\n---- Total time for all request = %s milliseconds"
+ "\n---- Total count of request = %s"
+ "\n---- Count of success request = %s";
//@formatter:on
public final TimedHttpRequest timedHttpRequest;
public final long duration;
public final int responseCode;
public final Exception exception;
public final TestRunStatus testRunStatus;
public TimedHttpRequestResult(final TimedHttpRequest timedHttpRequest, final long duration,
final int responseCode, final TestRunStatus testRunStatus) {
this.timedHttpRequest = timedHttpRequest;
this.duration = duration;
this.responseCode = responseCode;
this.testRunStatus = testRunStatus;
this.exception = null;
}
public TimedHttpRequestResult(final TimedHttpRequest timedHttpRequest, final Exception exception,
final TestRunStatus testRunStatus) {
this.timedHttpRequest = timedHttpRequest;
this.duration = -1L;
this.responseCode = -1;
this.testRunStatus = testRunStatus;
this.exception = exception;
}
boolean isSuccess() {
return this.responseCode == HttpURLConnection.HTTP_OK;
}
@Override
public String toString() {
return String.format(TO_STRING_FORMAT, this.timedHttpRequest.testRun.urlString, this.responseCode,
this.duration, this.testRunStatus.totalDurationSoFar, this.testRunStatus.totalRunSoFar,
this.testRunStatus.totalSuccessfulSoFar);
}
}
public static class TimedHttpRequest implements Callable<TimedHttpRequestResult> {
public final TestRun testRun;
public TimedHttpRequest(final TestRun testRun) {
this.testRun = testRun;
}
@Override
public TimedHttpRequestResult call() throws Exception {
final URL url = new URL(this.testRun.urlString);
final HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setRequestProperty("User-Agent", this.testRun.userAgentString);
final long startTime = System.nanoTime();
final int responseCode = httpURLConnection.getResponseCode();
final long endTime = System.nanoTime();
httpURLConnection.disconnect();
final long duration = TimeUnit.NANOSECONDS.toMillis(endTime - startTime);
final TimedHttpRequestResult timedHttpRequestResult = new TimedHttpRequestResult(this, duration,
responseCode, this.testRun.updateCounts(duration, responseCode));
System.out.println(timedHttpRequestResult);
return timedHttpRequestResult;
}
}
}
这是主要的问题为了我。它应该如何工作? – user3737721
你卡在哪里?如何创建一个类?如何编写这些方法?如何访问这些方法? – AlexR
这是我的主要问题。它应该如何工作?创建新类SyncronizedCounter {private long totalTimeMy = 0; public syncronized void incrementTime(long time){totalTimeMy + = time;} public syncronized void getTime(){return totalTimeMy;}}。比我应该在MyRunnable中创建instantce并在方法运行中更改它。但我如何获得最后的价值。我不知道如何在TestMain.class中做到这一点。 – user3737721