Merge branch 'master' into BAEL-1711-move-code-snippets
This commit is contained in:
+5
-2
@@ -55,12 +55,12 @@
|
||||
- [Introduction to BouncyCastle with Java](http://www.baeldung.com/java-bouncy-castle)
|
||||
- [Guide to google-http-client](http://www.baeldung.com/google-http-client)
|
||||
- [Interact with Google Sheets from Java](http://www.baeldung.com/google-sheets-java-client)
|
||||
- [Programatically Create, Configure, and Run a Tomcat Server] (http://www.baeldung.com/tomcat-programmatic-setup)
|
||||
- [Programatically Create, Configure, and Run a Tomcat Server](http://www.baeldung.com/tomcat-programmatic-setup)
|
||||
- [A Docker Guide for Java](http://www.baeldung.com/docker-java-api)
|
||||
- [Exceptions in Netty](http://www.baeldung.com/netty-exception-handling)
|
||||
- [Creating and Configuring Jetty 9 Server in Java](http://www.baeldung.com/jetty-java-programmatic)
|
||||
- [Introduction To OpenCSV](http://www.baeldung.com/opencsv)
|
||||
- [Introduction to Akka Actors in Java] (http://www.baeldung.com/akka-actors-java)
|
||||
- [Introduction to Akka Actors in Java](http://www.baeldung.com/akka-actors-java)
|
||||
- [Asynchronous HTTP with async-http-client in Java](https://github.com/eugenp/tutorials/tree/master/libraries)
|
||||
- [Introduction to Smooks](http://www.baeldung.com/smooks)
|
||||
- [WebSockets with AsyncHttpClient](http://www.baeldung.com/async-http-client-websockets)
|
||||
@@ -68,6 +68,9 @@
|
||||
- [Introduction to OpenCSV](http://www.baeldung.com/opencsv)
|
||||
- [A Guide to Unirest](http://www.baeldung.com/unirest)
|
||||
- [Introduction to Akka Actors in Java](http://www.baeldung.com/akka-actors-java)
|
||||
- [A Guide to Apache Commons Collections CollectionUtils](http://www.baeldung.com/apache-commons-collection-utils)
|
||||
- [A Guide to Byte Buddy](http://www.baeldung.com/byte-buddy)
|
||||
- [Java Concurrency Utility with JCTools](http://www.baeldung.com/java-concurrency-jc-tools)
|
||||
|
||||
The libraries module contains examples related to small libraries that are relatively easy to use and does not require any separate module of its own.
|
||||
|
||||
|
||||
+51
-14
@@ -11,20 +11,20 @@
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<!-- https://mvnrepository.com/artifact/com.typesafe.akka/akka-actor -->
|
||||
<!-- https://mvnrepository.com/artifact/com.typesafe.akka/akka-actor -->
|
||||
<dependency>
|
||||
<groupId>com.typesafe.akka</groupId>
|
||||
<artifactId>akka-actor_2.12</artifactId>
|
||||
<version>2.5.11</version>
|
||||
<version>${typesafe-akka.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.typesafe.akka</groupId>
|
||||
<artifactId>akka-testkit_2.12</artifactId>
|
||||
<version>2.5.11</version>
|
||||
<version>${typesafe-akka.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.asynchttpclient/async-http-client -->
|
||||
<dependency>
|
||||
<groupId>org.asynchttpclient</groupId>
|
||||
@@ -674,7 +674,7 @@
|
||||
<artifactId>milyn-smooks-all</artifactId>
|
||||
<version>${smooks.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<dependency>
|
||||
<groupId>com.mashape.unirest</groupId>
|
||||
<artifactId>unirest-java</artifactId>
|
||||
<version>${unirest.version}</version>
|
||||
@@ -686,8 +686,14 @@
|
||||
<artifactId>fugue</artifactId>
|
||||
<version>4.5.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jctools</groupId>
|
||||
<artifactId>jctools-core</artifactId>
|
||||
<version>${jctools.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>maven2-repository.dev.java.net</id>
|
||||
@@ -726,7 +732,7 @@
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>2.20</version>
|
||||
<version>${maven-failsafe-plugin.version}</version>
|
||||
<configuration>
|
||||
<systemProperties>
|
||||
<webdriver.chrome.driver>chromedriver</webdriver.chrome.driver>
|
||||
@@ -786,14 +792,41 @@
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- /Neuroph -->
|
||||
<!-- Borrowed from the 'jmh-java-benchmark-archetype' pom.xml -->
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.7.0</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<finalName>benchmarks</finalName>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||
<mainClass>org.openjdk.jmh.Main</mainClass>
|
||||
</transformer>
|
||||
</transformers>
|
||||
<filters>
|
||||
<filter>
|
||||
<!--
|
||||
Shading signed JARs will fail without this.
|
||||
http://stackoverflow.com/questions/999489/invalid-signature-file-when-attempting-to-run-a-jar
|
||||
-->
|
||||
<artifact>*:*</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/*.SF</exclude>
|
||||
<exclude>META-INF/*.DSA</exclude>
|
||||
<exclude>META-INF/*.RSA</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
@@ -866,7 +899,11 @@
|
||||
<infinispan.version>9.1.5.Final</infinispan.version>
|
||||
<opencsv.version>4.1</opencsv.version>
|
||||
<unirest.version>1.4.9</unirest.version>
|
||||
<jctools.version>2.1.2</jctools.version>
|
||||
<commons-codec-version>1.10.L001</commons-codec-version>
|
||||
<jets3t-version>0.9.4.0006L</jets3t-version>
|
||||
<jctools.version>2.1.2</jctools.version>
|
||||
<typesafe-akka.version>2.5.11</typesafe-akka.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.baeldung.jctools;
|
||||
|
||||
import org.jctools.queues.MpmcArrayQueue;
|
||||
import org.jctools.queues.atomic.MpmcAtomicArrayQueue;
|
||||
import org.openjdk.jmh.annotations.*;
|
||||
import org.openjdk.jmh.infra.Control;
|
||||
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@BenchmarkMode(Mode.SampleTime)
|
||||
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||
@Fork(1)
|
||||
@Warmup(iterations = 1)
|
||||
@Measurement(iterations = 3)
|
||||
@State(Scope.Group)
|
||||
public class MpmcBenchmark {
|
||||
|
||||
public static final String PARAM_UNSAFE = "MpmcArrayQueue";
|
||||
public static final String PARAM_AFU = "MpmcAtomicArrayQueue";
|
||||
public static final String PARAM_JDK = "ArrayBlockingQueue";
|
||||
|
||||
public static final int PRODUCER_THREADS_NUMBER = 32;
|
||||
public static final int CONSUMER_THREADS_NUMBER = 32;
|
||||
|
||||
public static final String GROUP_NAME = "MyGroup";
|
||||
|
||||
public static final int CAPACITY = 128;
|
||||
|
||||
@Param({PARAM_UNSAFE, PARAM_AFU, PARAM_JDK})
|
||||
public volatile String implementation;
|
||||
|
||||
public volatile Queue<Long> queue;
|
||||
|
||||
@Setup(Level.Trial)
|
||||
public void setUp() {
|
||||
switch (implementation) {
|
||||
case PARAM_UNSAFE:
|
||||
queue = new MpmcArrayQueue<>(CAPACITY);
|
||||
break;
|
||||
case PARAM_AFU:
|
||||
queue = new MpmcAtomicArrayQueue<>(CAPACITY);
|
||||
break;
|
||||
case PARAM_JDK:
|
||||
queue = new ArrayBlockingQueue<>(CAPACITY);
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unsupported implementation " + implementation);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Benchmark
|
||||
@Group(GROUP_NAME)
|
||||
@GroupThreads(PRODUCER_THREADS_NUMBER)
|
||||
public void write(Control control) {
|
||||
//noinspection StatementWithEmptyBody
|
||||
while (!control.stopMeasurement && !queue.offer(1L)) {
|
||||
// Is intentionally left blank
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Group(GROUP_NAME)
|
||||
@GroupThreads(CONSUMER_THREADS_NUMBER)
|
||||
public void read(Control control) {
|
||||
//noinspection StatementWithEmptyBody
|
||||
while (!control.stopMeasurement && queue.poll() == null) {
|
||||
// Is intentionally left blank
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
## How to build and run the JMH benchmark
|
||||
|
||||
Execute the following from the project's root:
|
||||
```bash
|
||||
mvn clean install
|
||||
java -jar ./target/benchmarks.jar MpmcBenchmark -si true
|
||||
```
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.baeldung.jctools;
|
||||
|
||||
import org.jctools.queues.SpscArrayQueue;
|
||||
import org.jctools.queues.SpscChunkedArrayQueue;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.IntConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
|
||||
public class JCToolsUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenMultipleProducers_whenSpscQueueUsed_thenNoWarningOccurs() throws InterruptedException {
|
||||
SpscArrayQueue<Integer> queue = new SpscArrayQueue<Integer>(2);
|
||||
|
||||
Thread producer1 = new Thread(() -> {
|
||||
queue.offer(1);
|
||||
});
|
||||
producer1.start();
|
||||
producer1.join();
|
||||
|
||||
Thread producer2 = new Thread(() -> {
|
||||
queue.offer(2);
|
||||
});
|
||||
producer2.start();
|
||||
producer2.join();
|
||||
|
||||
Set<Integer> fromQueue = new HashSet<>();
|
||||
Thread consumer = new Thread(() -> queue.drain(fromQueue::add));
|
||||
consumer.start();
|
||||
consumer.join();
|
||||
|
||||
assertThat(fromQueue).containsOnly(1, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenQueueIsFull_thenNoMoreElementsCanBeAdded() throws InterruptedException {
|
||||
SpscChunkedArrayQueue<Integer> queue = new SpscChunkedArrayQueue<>(8, 16);
|
||||
assertThat(queue.capacity()).isEqualTo(16);
|
||||
|
||||
CountDownLatch startConsuming = new CountDownLatch(1);
|
||||
CountDownLatch awakeProducer = new CountDownLatch(1);
|
||||
AtomicReference<Throwable> error = new AtomicReference<>();
|
||||
Thread producer = new Thread(() -> {
|
||||
IntStream.range(0, queue.capacity()).forEach(i -> {
|
||||
assertThat(queue.offer(i)).isTrue();
|
||||
});
|
||||
assertThat(queue.offer(queue.capacity())).isFalse();
|
||||
startConsuming.countDown();
|
||||
try {
|
||||
awakeProducer.await();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
assertThat(queue.offer(queue.capacity())).isTrue();
|
||||
});
|
||||
producer.setUncaughtExceptionHandler((t, e) -> {
|
||||
error.set(e);
|
||||
startConsuming.countDown();
|
||||
});
|
||||
producer.start();
|
||||
|
||||
startConsuming.await();
|
||||
|
||||
if (error.get() != null) {
|
||||
fail("Producer's assertion failed", error.get());
|
||||
}
|
||||
|
||||
Set<Integer> fromQueue = new HashSet<>();
|
||||
queue.drain(fromQueue::add);
|
||||
awakeProducer.countDown();
|
||||
producer.join();
|
||||
queue.drain(fromQueue::add);
|
||||
|
||||
assertThat(fromQueue).containsAll(IntStream.range(0, 17).boxed().collect(Collectors.toSet()));
|
||||
}
|
||||
}
|
||||
@@ -52,16 +52,12 @@ public class EmbeddedChannelUnitTest {
|
||||
"/calculate?a=10&b=5");
|
||||
wrongHttpRequest.headers().add("Operator", "Add");
|
||||
|
||||
Throwable thrownException = catchThrowable(() -> {
|
||||
// send invalid HTTP request to server and expect and error
|
||||
channel.pipeline().fireChannelRead(wrongHttpRequest);
|
||||
channel.checkException();
|
||||
Assertions.failBecauseExceptionWasNotThrown(UnsupportedOperationException.class);
|
||||
});
|
||||
|
||||
assertThat(thrownException)
|
||||
.isInstanceOf(UnsupportedOperationException.class)
|
||||
.hasMessage("HTTP method not supported");
|
||||
assertThatThrownBy(() -> {
|
||||
// send invalid HTTP request to server and expect and error
|
||||
channel.pipeline().fireChannelRead(wrongHttpRequest);
|
||||
channel.checkException();
|
||||
}).isInstanceOf(UnsupportedOperationException.class)
|
||||
.hasMessage("HTTP method not supported");
|
||||
|
||||
FullHttpResponse errorHttpResponse = channel.readOutbound();
|
||||
String errorHttpResponseContent = errorHttpResponse.content().toString(Charset.defaultCharset());
|
||||
@@ -77,15 +73,11 @@ public class EmbeddedChannelUnitTest {
|
||||
"/calculate?a=10&b=5");
|
||||
wrongHttpRequest.headers().add("Operator", "Invalid_operation");
|
||||
|
||||
Throwable thrownException = catchThrowable(() -> {
|
||||
// send invalid HTTP request to server and expect and error
|
||||
channel.writeInbound(wrongHttpRequest);
|
||||
Assertions.failBecauseExceptionWasNotThrown(IllegalArgumentException.class);
|
||||
});
|
||||
|
||||
// the HttpMessageHandler does not handle the exception and throws it down the
|
||||
// pipeline
|
||||
assertThat(thrownException).isInstanceOf(IllegalArgumentException.class).hasMessage("Operation not defined");
|
||||
// the HttpMessageHandler does not handle the exception and throws it down the pipeline
|
||||
assertThatThrownBy(() -> {
|
||||
channel.writeInbound(wrongHttpRequest);
|
||||
}).isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Operation not defined");
|
||||
|
||||
// the outbound message is a HTTP response with the status code 500
|
||||
FullHttpResponse errorHttpResponse = channel.readOutbound();
|
||||
|
||||
Reference in New Issue
Block a user