Example usage for java.util.concurrent.atomic AtomicInteger incrementAndGet

List of usage examples for java.util.concurrent.atomic AtomicInteger incrementAndGet

Introduction

In this page you can find the example usage for java.util.concurrent.atomic AtomicInteger incrementAndGet.

Prototype

public final int incrementAndGet() 

Source Link

Document

Atomically increments the current value, with memory effects as specified by VarHandle#getAndAdd .

Usage

From source file:com.alibaba.napoli.client.benchmark.NapoliNormalQueueTest.java

@Test
public void sendMessageWithSenderStoreEnableTest() throws Exception {

    log.info("start to execute sendMessageWithSenderStoreEnableTest");
    long beginQueueSize = JmxUtil.getQueueSize(sendConnector.getAddress(), queueName);

    qSender = new DefaultAsyncSender();
    qSender.setConnector(sendConnector);
    qSender.setName(queueName);// w w  w. ja va 2  s  . c o  m

    qSender.setStoreEnable(true);
    qSender.setReprocessInterval(10000 * 1000 * 1000);

    qSender.init();

    int tc = 10;

    log.info("yanny requestcount = " + System.getProperty("requestCount") + ", begin queue size is "
            + beginQueueSize);
    final int tp = Integer.parseInt(System.getProperty("requestCount", "20"));
    final Semaphore semaphore = new Semaphore(tc);
    final AtomicInteger sumCount = new AtomicInteger();

    final AtomicInteger requestCount = new AtomicInteger();
    long startTime = System.currentTimeMillis();
    log.info("Yanny start send request " + startTime);

    for (int i = 0; i < tc; i++) {
        Thread t = new Thread("thread--" + i) {
            public void run() {
                try {
                    //?tringap??Serializable
                    semaphore.acquire();
                    Person person = new Person();

                    person.setLoginName("superman");
                    person.setEmail("sm@1.com");
                    person.setPenName("pname");
                    person.setStatus(PersonStatus.ENABLED);

                    for (int j = 0; j < tp; j++) {
                        //      log.info("hello");
                        int id = requestCount.incrementAndGet();
                        person.setPersonId("" + id);

                        //?? ??true???alse                        
                        boolean result = qSender.send(person);
                        if (!result) {
                            log.info("----------------send to queue " + "result is false. personid=" + j);
                        } else {
                            sumCount.incrementAndGet();
                        }
                    }
                } catch (Throwable t) {
                    t.printStackTrace();
                } finally {
                    semaphore.release();
                }
            }
        };
        t.start();
    }

    while (semaphore.availablePermits() != tc) {
        Thread.sleep(100);
    }

    int totalRequest = tc * tp;

    long endTime = System.currentTimeMillis();
    log.info("yanny: send " + totalRequest + " message, take " + (endTime - startTime) + " milseconds");

    JmxUtil.waitTillQueueSizeAsTarget(sendConnector.getAddress(), queueName, beginQueueSize);

    endTime = System.currentTimeMillis();

    String errorMessage = "";

    long qBdbCount = NapoliTestUtil.getStoreSize(sendConnector.getSenderKVStore(qSender.getName()));

    log.info("yanny totalRequest " + totalRequest + " send queue success " + sumCount + " local store count:"
            + qBdbCount + " queue received " + qWorker.getAccessNum() + " take " + (endTime - startTime)
            + " milseconds");

    log.info(initConsumeMessage);

    log.info("NapoliNormalQueueTest's success=" + qWorker.getAccessNum() + " bdb's size=" + qBdbCount);

    //with store enabled, all send should succeed.
    if (qSender.getStoreEnable()) {
        if (sumCount.get() != totalRequest) {
            errorMessage += ";with store enabled, all send should return success, but not equal now. send succeed "
                    + sumCount.get() + "; total request:" + totalRequest;
        }
    } else {
        if (sumCount.get() < totalRequest * 0.95) {
            errorMessage += ";with store disabled, expected more than 95% message send succeed, total request:"
                    + totalRequest + "; send succeed " + sumCount.get();
        }
    }

    if (sumCount.get() < qWorker.getAccessNum()) {
        errorMessage += ";queue should not have success messages more than send succeed" + sumCount.get()
                + " (success " + qWorker.getAccessNum() + ")";
    }

    if ((sumCount.get() - qBdbCount) > qWorker.getAccessNum()) {
        errorMessage += ";queue received message (" + qWorker.getAccessNum()
                + ") less than send succeed - local stored message, message lost "
                + (sumCount.get() - qBdbCount);
    }

    int allowedDiff = (int) Math.round(sumCount.get() * 0.001);

    if (((qWorker.getAccessNum() + qBdbCount) - sumCount.get()) > allowedDiff) {
        errorMessage += "queue received message should not have more than send succeed + " + allowedDiff
                + " than allowed (0.1%), gap " + ((qWorker.getAccessNum() + qBdbCount) - sumCount.get());
    }

    assertTrue(errorMessage, errorMessage.equals(""));

    verify(napoliSenderStat, atMost(qWorker.getAccessNum())).sendSuccess(anyLong(), anyLong());
    verify(napoliSenderStat, atLeast((int) (sumCount.get() - qBdbCount))).sendSuccess(anyLong(), anyLong());
    verify(napoliSenderStat, times((int) qBdbCount)).sendFailure(anyLong(), anyLong());

    verify(napoliReceiverStat, times((int) qWorker.getAccessNum())).receiveSuccess(anyLong(), anyLong());
}

From source file:org.dasein.cloud.azurepack.tests.compute.AzurePackVirtualMachineSupportTest.java

@Test
public void terminateShouldSendCorrectRequest() throws CloudException, InternalException {
    final AtomicInteger deleteCount = new AtomicInteger(0);
    new GetOrListVirtualMachinesRequestExecutorMockUp() {
        @Mock// w  w w.  j  a  v a 2  s.  c  om
        public void $init(CloudProvider provider, HttpClientBuilder clientBuilder, HttpUriRequest request,
                ResponseHandler handler) {
            String requestUri = request.getURI().toString();
            if (request.getMethod().equals("DELETE") && requestUri
                    .equals(String.format(VM_RESOURCES, ENDPOINT, ACCOUNT_NO, DATACENTER_ID, VM_1_ID))) {
                requestResourceType = 11;
            } else {
                super.$init(provider, clientBuilder, request, handler);
            }
        }

        @Mock
        public Object execute() {
            if (requestResourceType == 11) {
                deleteCount.incrementAndGet();
                return "";
            } else {
                return super.execute();
            }
        }
    };
    azurePackVirtualMachineSupport.terminate(VM_1_ID, "no reason");
    assertEquals("terminate doesn't send DELETE request", 1, deleteCount.get());
}

From source file:com.alibaba.napoli.client.benchmark.NapoliNormalQueueTest.java

@Test
public void sendMessageWithSenderStoreDisabledTest() throws Exception {

    log.info("start to execute sendMessageWithSenderStoreDisabledTest");

    long beginQueueSize = JmxUtil.getQueueSize(sendConnector.getAddress(), queueName);

    qSender = new DefaultAsyncSender();
    qSender.setConnector(sendConnector);
    qSender.setName(queueName);//from  w  w  w  . j a  va2  s  .c  o  m

    qSender.setStoreEnable(false);
    qSender.setReprocessInterval(10000 * 1000 * 1000);

    qSender.init();

    int tc = 10;
    log.info("yanny requestcount = " + System.getProperty("requestCount"));
    final int tp = Integer.parseInt(System.getProperty("requestCount", "20"));
    final Semaphore semaphore = new Semaphore(tc);
    final AtomicInteger sumCount = new AtomicInteger();

    final AtomicInteger requestCount = new AtomicInteger();
    long startTime = System.currentTimeMillis();
    log.info("Yanny start send request " + startTime);

    for (int i = 0; i < tc; i++) {
        Thread t = new Thread("thread--" + i) {
            public void run() {
                try {
                    //?tringap??Serializable
                    semaphore.acquire();
                    Person person = new Person();

                    person.setLoginName("superman");
                    person.setEmail("sm@1.com");
                    person.setPenName("pname");
                    person.setStatus(PersonStatus.ENABLED);

                    for (int j = 0; j < tp; j++) {
                        //      log.info("hello");
                        int id = requestCount.incrementAndGet();
                        person.setPersonId("" + id);

                        //?? ??true???alse                        
                        boolean result = qSender.send(person);
                        if (!result) {
                            log.info("----------------send to queue " + "result is false. personid=" + j);
                        } else {
                            sumCount.incrementAndGet();
                        }
                    }
                } catch (Throwable t) {
                    t.printStackTrace();
                } finally {
                    semaphore.release();
                }
            }
        };
        t.start();
    }

    while (semaphore.availablePermits() != tc) {
        Thread.sleep(100);
    }
    int totalRequest = tc * tp;

    long endTime = System.currentTimeMillis();
    log.info("yanny: send " + totalRequest + " message, take " + (endTime - startTime) + " milseconds");

    JmxUtil.waitTillQueueSizeAsTarget(sendConnector.getAddress(), queueName, beginQueueSize);

    endTime = System.currentTimeMillis();

    String errorMessage = "";

    long qBdbCount = NapoliTestUtil.getStoreSize(sendConnector.getSenderKVStore(qSender.getName()));
    log.info("yanny totalRequest " + totalRequest + " send queue success " + sumCount + " local store count:"
            + qBdbCount + " queue received " + qWorker.getAccessNum() + " take " + (endTime - startTime)
            + " milseconds");

    log.info(initConsumeMessage);

    log.info("NapoliNormalQueueTest's success=" + qWorker.getAccessNum() + " bdb's size=" + qBdbCount);

    if (qBdbCount > 0) {
        errorMessage += ";with store disabled, local store count should be empty, but is " + qBdbCount;
    }

    //with store enabled, all send should succeed.
    if (qSender.getStoreEnable()) {
        if (sumCount.get() != totalRequest) {
            errorMessage += ";with store enabled, all send should return success, but not equal now. send succeed "
                    + sumCount.get() + "; total request:" + totalRequest;
        }
    } else {
        if (sumCount.get() < totalRequest * 0.95) {
            errorMessage += ";with store disabled, expected more than 95% message send succeed, total request:"
                    + totalRequest + "; send succeed " + sumCount.get();
        }
    }

    //?????otalRequest,??>=sum
    if (totalRequest < qWorker.getAccessNum()) {
        errorMessage += ";queue should not have success messages more than send succeed" + sumCount.get()
                + " (success " + qWorker.getAccessNum() + ")";
    }

    //?qBdbCount?
    if ((sumCount.get() - qBdbCount) > qWorker.getAccessNum()) {
        errorMessage += ";queue received message (" + qWorker.getAccessNum()
                + ") less than send succeed - local stored message, message lost "
                + (sumCount.get() - qBdbCount);
    }

    int allowedDiff = (int) Math.round(sumCount.get() * 0.001);

    if (((qWorker.getAccessNum() + qBdbCount) - sumCount.get()) > allowedDiff) {
        errorMessage += "queue received message should not have more than send succeed + " + allowedDiff
                + " than allowed (0.1%), gap " + ((qWorker.getAccessNum() + qBdbCount) - sumCount.get());
    }

    assertTrue(errorMessage, errorMessage.equals(""));

    verify(napoliSenderStat, atMost(qWorker.getAccessNum())).sendSuccess(anyLong(), anyLong());
    verify(napoliSenderStat, atLeast((int) (sumCount.get() - qBdbCount))).sendSuccess(anyLong(), anyLong());
    verify(napoliSenderStat, times(totalRequest - sumCount.get())).sendFalse(anyLong(), anyLong());

    verify(napoliSenderStat, times((int) qBdbCount)).sendFailure(anyLong(), anyLong());

    verify(napoliReceiverStat, times((int) qWorker.getAccessNum())).receiveSuccess(anyLong(), anyLong());
}

From source file:com.couchbase.client.core.endpoint.query.QueryHandlerTest.java

@Test
public void shouldGroupErrorsAndWarnings() throws InterruptedException {
    String response = Resources.read("errors_and_warnings.json", this.getClass());
    HttpResponse responseHeader = new DefaultHttpResponse(HttpVersion.HTTP_1_1,
            new HttpResponseStatus(200, "OK"));
    HttpContent responseChunk = new DefaultLastHttpContent(Unpooled.copiedBuffer(response, CharsetUtil.UTF_8));

    GenericQueryRequest requestMock = mock(GenericQueryRequest.class);
    queue.add(requestMock);/*from  w ww. ja  v  a  2s  .  co  m*/
    channel.writeInbound(responseHeader, responseChunk);
    latch.await(1, TimeUnit.SECONDS);
    assertEquals(1, firedEvents.size());
    GenericQueryResponse inbound = (GenericQueryResponse) firedEvents.get(0);

    Map<String, Object> expectedMetrics = expectedMetricsCounts(1, 0);
    expectedMetrics.put("warningCount", 1);

    final AtomicInteger count = new AtomicInteger(0);
    assertResponse(inbound, false, ResponseStatus.FAILURE, FAKE_REQUESTID, FAKE_CLIENTID, "fatal", null,
            new Action1<ByteBuf>() {
                @Override
                public void call(ByteBuf byteBuf) {
                    fail("no result expected");
                }
            }, new Action1<ByteBuf>() {
                @Override
                public void call(ByteBuf buf) {
                    count.incrementAndGet();
                    String response = buf.toString(CharsetUtil.UTF_8);
                    buf.release();
                    try {
                        Map error = mapper.readValue(response, Map.class);
                        assertEquals(5, error.size());
                        if (count.get() == 1) {
                            assertEquals(new Integer(4100), error.get("code"));
                            assertEquals(Boolean.FALSE, error.get("temp"));
                            assertEquals("Parse Error", error.get("msg"));
                        } else if (count.get() == 2) {
                            assertEquals(3, error.get("sev"));
                            assertEquals(201, error.get("code"));
                            assertEquals(Boolean.TRUE, error.get("temp"));
                            assertEquals("Nothing to do", error.get("msg"));
                            assertEquals("nothingToDo", error.get("name"));
                        }
                    } catch (IOException e) {
                        fail();
                    }
                }
            }, expectedMetrics);
    assertEquals(2, count.get());
}

From source file:com.github.gfx.android.orma.example.fragment.BenchmarkFragment.java

Single<Result> startSelectAllWithHandWritten() {
    return Single.fromCallable(() -> {
        long result = runWithBenchmark(() -> {
            AtomicInteger count = new AtomicInteger();

            Database db = hw.getReadableDatabase();
            Cursor cursor = db.query("todo", new String[] { "id, title, content, done, createdTime" }, null,
                    null, null, null, "createdTime ASC", null // whereClause, whereArgs, groupBy, having, orderBy, limit
            );//from w  w  w  .j a v a  2  s .c om

            if (cursor.moveToFirst()) {
                int titleIndex = cursor.getColumnIndexOrThrow("title");
                int contentIndex = cursor.getColumnIndexOrThrow("content");
                int createdTimeIndex = cursor.getColumnIndexOrThrow("createdTime");
                do {
                    @SuppressWarnings("unused")
                    String title = cursor.getString(titleIndex);
                    @SuppressWarnings("unused")
                    String content = cursor.getString(contentIndex);
                    @SuppressWarnings("unused")
                    Date createdTime = new Date(cursor.getLong(createdTimeIndex));

                    count.incrementAndGet();
                } while (cursor.moveToNext());
            }
            cursor.close();

            long dbCount = longForQuery(db, "SELECT COUNT(*) FROM todo", null);
            if (dbCount != count.get()) {
                throw new AssertionError("unexpected get: " + count.get() + " != " + dbCount);
            }

            Log.d(TAG, "HandWritten/forEachAll count: " + count);
        });
        return new Result("HandWritten/forEachAll", result);
    }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
}

From source file:com.github.totyumengr.minicubes.cluster.TimeSeriesMiniCubeManagerHzImpl.java

@Override
public <T> List<T> execute(Callable<T> task, Collection<String> cubeIds, int timeoutSeconds) {

    Set<Member> members = hazelcastInstance.getCluster().getMembers();
    Set<Member> selected = new LinkedHashSet<Member>();
    if (cubeIds != null && !cubeIds.isEmpty()) {
        List<String> cubeNodes = cubeIds.stream().map(e -> e.split("@")[1]).collect(Collectors.toList());
        for (Member m : members) {
            if (cubeNodes.contains(m.getSocketAddress().toString())) {
                selected.add(m);//www  .  j  a  va  2  s.co m
            }
        }
    } else {
        selected.addAll(members);
        LOGGER.warn("Select all members {} in cluster to execute on.", selected);
    }

    final int size = selected.size();
    LOGGER.debug("Start to run task {} on {}", task, selected);

    // Call distributed execute service to run it.
    final List<T> result = new ArrayList<T>(selected.size());
    final List<Exception> exceptionResult = new ArrayList<Exception>();
    CountDownLatch cdl = new CountDownLatch(1);
    AtomicInteger completedCount = new AtomicInteger(0);
    hazelcastInstance.getExecutorService(DISTRIBUTED_EXECUTOR).submitToMembers(task, selected,
            new MultiExecutionCallback() {

                @SuppressWarnings("unchecked")
                @Override
                public void onResponse(Member member, Object value) {
                    int i = completedCount.incrementAndGet();
                    LOGGER.debug("Completed of {}/{}, {} and {}", i, size, member, value);
                    if (value instanceof Exception) {
                        exceptionResult.add((Exception) value);
                    } else {
                        result.add((T) value);
                    }
                }

                @Override
                public void onComplete(Map<Member, Object> values) {
                    LOGGER.info("Successfully execute {} on cluster, collect {} result.", task, values.size());
                    cdl.countDown();
                }
            });

    if (completedCount.get() < size) {
        // FIXME: When some task do not executed. Maybe reject? error?
    }

    try {
        cdl.await(timeoutSeconds > 0 ? timeoutSeconds : Integer.MAX_VALUE, TimeUnit.SECONDS);
    } catch (InterruptedException e) {
        // Ignore
    }

    // Exception handled
    if (!exceptionResult.isEmpty()) {
        LOGGER.error("{} exceptions occurred when try to execute {} on {}", exceptionResult.size(), task,
                ObjectUtils.getDisplayString(selected));
        for (int i = 0; i < exceptionResult.size(); i++) {
            LOGGER.error("#1 exception === ", exceptionResult.get(i));
        }
        throw new RuntimeException("Exception occurred when try to execute, please see detail logs above.");
    }

    return result;
}

From source file:com.twitter.distributedlog.lock.TestZKSessionLock.java

@Test(timeout = 60000)
public void testExecuteLockAction() throws Exception {
    String lockPath = "/test-execute-lock-action";
    String clientId = "test-execute-lock-action-" + System.currentTimeMillis();

    ZKSessionLock lock = new ZKSessionLock(zkc, lockPath, clientId, lockStateExecutor);

    final AtomicInteger counter = new AtomicInteger(0);

    // lock action would be executed in same epoch
    final CountDownLatch latch1 = new CountDownLatch(1);
    lock.executeLockAction(lock.getEpoch().get(), new LockAction() {
        @Override//from w  w  w. java  2  s  . co m
        public void execute() {
            counter.incrementAndGet();
            latch1.countDown();
        }

        @Override
        public String getActionName() {
            return "increment1";
        }
    });
    latch1.await();
    assertEquals("counter should be increased in same epoch", 1, counter.get());

    // lock action would not be executed in same epoch
    final CountDownLatch latch2 = new CountDownLatch(1);
    lock.executeLockAction(lock.getEpoch().get() + 1, new LockAction() {
        @Override
        public void execute() {
            counter.incrementAndGet();
        }

        @Override
        public String getActionName() {
            return "increment2";
        }
    });
    lock.executeLockAction(lock.getEpoch().get(), new LockAction() {
        @Override
        public void execute() {
            latch2.countDown();
        }

        @Override
        public String getActionName() {
            return "countdown";
        }
    });
    latch2.await();
    assertEquals("counter should not be increased in different epochs", 1, counter.get());

    // lock action would not be executed in same epoch and promise would be satisfied with exception
    Promise<BoxedUnit> promise = new Promise<BoxedUnit>();
    lock.executeLockAction(lock.getEpoch().get() + 1, new LockAction() {
        @Override
        public void execute() {
            counter.incrementAndGet();
        }

        @Override
        public String getActionName() {
            return "increment3";
        }
    }, promise);
    try {
        Await.result(promise);
        fail("Should satisfy promise with epoch changed exception.");
    } catch (EpochChangedException ece) {
        // expected
    }
    assertEquals("counter should not be increased in different epochs", 1, counter.get());

    lockStateExecutor.shutdown();
}

From source file:io.atomix.protocols.gossip.map.AntiEntropyMapDelegate.java

/**
 * Requests all updates from each peer in the provided list of peers.
 * <p>//from  w  ww  . ja  v a 2s  .c om
 * The returned future will be completed once at least one peer bootstraps this map or bootstrap requests to all peers
 * fail.
 *
 * @param peers the list of peers from which to request updates
 * @return a future to be completed once updates have been received from at least one peer
 */
private CompletableFuture<Void> requestBootstrapFromPeers(List<MemberId> peers) {
    if (peers.isEmpty()) {
        return CompletableFuture.completedFuture(null);
    }
    CompletableFuture<Void> future = new CompletableFuture<>();
    final int totalPeers = peers.size();
    AtomicBoolean successful = new AtomicBoolean();
    AtomicInteger totalCount = new AtomicInteger();
    AtomicReference<Throwable> lastError = new AtomicReference<>();

    // Iterate through all of the peers and send a bootstrap request. On the first peer that returns
    // a successful bootstrap response, complete the future. Otherwise, if no peers respond with any
    // successful bootstrap response, the future will be completed with the last exception.
    for (MemberId peer : peers) {
        requestBootstrapFromPeer(peer).whenComplete((result, error) -> {
            if (error == null) {
                if (successful.compareAndSet(false, true)) {
                    future.complete(null);
                } else if (totalCount.incrementAndGet() == totalPeers) {
                    Throwable e = lastError.get();
                    if (e != null) {
                        future.completeExceptionally(e);
                    }
                }
            } else {
                if (!successful.get() && totalCount.incrementAndGet() == totalPeers) {
                    future.completeExceptionally(error);
                } else {
                    lastError.set(error);
                }
            }
        });
    }
    return future;
}

From source file:com.spectralogic.ds3client.integration.Smoke_Test.java

@Test
public void putDirectoryWithOtherObjects() throws IOException, XmlProcessingException {
    assumeVersion1_2(client);/*from  w  ww.j av  a 2  s . c  om*/

    final String bucketName = "mixedPutDir";

    try {

        final byte[] content = "I'm text with some more data so that it gets flushed to the output cache."
                .getBytes(Charset.forName("UTF-8"));

        final List<Ds3Object> objs = Lists.newArrayList(new Ds3Object("dir/"),
                new Ds3Object("obj.txt", content.length));

        HELPERS.ensureBucketExists(bucketName, envDataPolicyId);

        final Ds3ClientHelpers.Job job = HELPERS.startWriteJob(bucketName, objs);

        final AtomicInteger counter = new AtomicInteger(0);

        job.transfer(new Ds3ClientHelpers.ObjectChannelBuilder() {
            @Override
            public SeekableByteChannel buildChannel(final String key) throws IOException {
                counter.incrementAndGet();
                return new ByteArraySeekableByteChannel(content);
            }
        });

        final GetBucketResponse response = client.getBucket(new GetBucketRequest(bucketName));

        assertThat(response.getListBucketResult().getObjects().size(), is(2));
        assertThat(counter.get(), is(1));

    } finally {
        deleteAllContents(client, bucketName);
    }
}

From source file:org.apache.distributedlog.lock.TestZKSessionLock.java

@Test(timeout = 60000)
public void testExecuteLockAction() throws Exception {
    String lockPath = "/test-execute-lock-action";
    String clientId = "test-execute-lock-action-" + System.currentTimeMillis();

    ZKSessionLock lock = new ZKSessionLock(zkc, lockPath, clientId, lockStateExecutor);

    final AtomicInteger counter = new AtomicInteger(0);

    // lock action would be executed in same epoch
    final CountDownLatch latch1 = new CountDownLatch(1);
    lock.executeLockAction(lock.getEpoch(), new LockAction() {
        @Override// w w w.  j av a2 s.  c o m
        public void execute() {
            counter.incrementAndGet();
            latch1.countDown();
        }

        @Override
        public String getActionName() {
            return "increment1";
        }
    });
    latch1.await();
    assertEquals("counter should be increased in same epoch", 1, counter.get());

    // lock action would not be executed in same epoch
    final CountDownLatch latch2 = new CountDownLatch(1);
    lock.executeLockAction(lock.getEpoch() + 1, new LockAction() {
        @Override
        public void execute() {
            counter.incrementAndGet();
        }

        @Override
        public String getActionName() {
            return "increment2";
        }
    });
    lock.executeLockAction(lock.getEpoch(), new LockAction() {
        @Override
        public void execute() {
            latch2.countDown();
        }

        @Override
        public String getActionName() {
            return "countdown";
        }
    });
    latch2.await();
    assertEquals("counter should not be increased in different epochs", 1, counter.get());

    // lock action would not be executed in same epoch and promise would be satisfied with exception
    CompletableFuture<Void> promise = new CompletableFuture<Void>();
    lock.executeLockAction(lock.getEpoch() + 1, new LockAction() {
        @Override
        public void execute() {
            counter.incrementAndGet();
        }

        @Override
        public String getActionName() {
            return "increment3";
        }
    }, promise);
    try {
        Utils.ioResult(promise);
        fail("Should satisfy promise with epoch changed exception.");
    } catch (EpochChangedException ece) {
        // expected
    }
    assertEquals("counter should not be increased in different epochs", 1, counter.get());

    lockStateExecutor.shutdown();
}