AtomicReference新jdk特性

简介: AtomicReference新jdk特性

对应的单元测试:

import org.junit.jupiter.api.Test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

class AtomicReferenceTest {

    @Test
    void testGetSetPlain() throws InterruptedException {
        AtomicReference<String> ref = new AtomicReference<>("initial");
        int numberOfThreads = 10;
        ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);

        for (int i = 0; i < numberOfThreads; i++) {
            executor.submit(() -> ref.setPlain("new"));
        }

        executor.shutdown();
        assertTrue(executor.awaitTermination(1, TimeUnit.MINUTES));
        assertEquals("new", ref.getPlain());
    }

    @Test
    void testGetSetAcquireRelease() throws InterruptedException {
        AtomicReference<String> ref = new AtomicReference<>("initial");
        int numberOfThreads = 10;
        ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);

        for (int i = 0; i < numberOfThreads; i++) {
            executor.submit(() -> ref.setRelease("new"));
        }

        executor.shutdown();
        assertTrue(executor.awaitTermination(1, TimeUnit.MINUTES));
        assertEquals("new", ref.getAcquire());
    }

    @Test
    void testGetSetOpaque() throws InterruptedException {
        AtomicReference<String> ref = new AtomicReference<>("initial");
        int numberOfThreads = 10;
        ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);

        for (int i = 0; i < numberOfThreads; i++) {
            executor.submit(() -> ref.setOpaque("new"));
        }

        executor.shutdown();
        assertTrue(executor.awaitTermination(1, TimeUnit.MINUTES));
        assertEquals("new", ref.getOpaque());
    }

    @Test
    void testCompareAndExchange() throws InterruptedException {
        AtomicReference<String> ref = new AtomicReference<>("initial");
        int numberOfThreads = 10;
        ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);

        for (int i = 0; i < numberOfThreads; i++) {
            executor.submit(() -> ref.compareAndExchange("initial", "changed"));
        }

        executor.shutdown();
        assertTrue(executor.awaitTermination(1, TimeUnit.MINUTES));
        assertEquals("changed", ref.get());
    }

    @Test
    void testCompareAndExchangeAcquireRelease() throws InterruptedException {
        AtomicReference<String> ref = new AtomicReference<>("initial");
        ExecutorService executor = Executors.newSingleThreadExecutor();

        executor.submit(() -> assertEquals("initial", ref.compareAndExchangeAcquire("initial", "changed")));
        executor.submit(() -> assertEquals("changed", ref.get()));
        executor.submit(() -> assertEquals("changed", ref.compareAndExchangeRelease("changed", "new")));
        executor.submit(() -> assertEquals("new", ref.get()));

        executor.shutdown();
        assertTrue(executor.awaitTermination(1, TimeUnit.MINUTES));
    }

    @Test
    void testWeakCompareAndSetVolatile() throws InterruptedException {
        AtomicReference<String> ref = new AtomicReference<>("initial");
        int numberOfThreads = 10;
        ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);

        for (int i = 0; i < numberOfThreads; i++) {
            executor.submit(() -> assertTrue(ref.weakCompareAndSetVolatile("initial", "changed")));
        }

        executor.shutdown();
        assertTrue(executor.awaitTermination(1, TimeUnit.MINUTES));
        assertEquals("changed", ref.get());
    }

    @Test
    void testWeakCompareAndSetAcquireRelease() throws InterruptedException {
        AtomicReference<String> ref = new AtomicReference<>("initial");
        ExecutorService executor = Executors.newSingleThreadExecutor();

        executor.submit(() -> assertTrue(ref.weakCompareAndSetAcquire("initial", "changed")));
        executor.submit(() -> assertEquals("changed", ref.get()));
        executor.submit(() -> assertTrue(ref.weakCompareAndSetRelease("changed", "new")));
        executor.submit(() -> assertEquals("new", ref.get()));

        executor.shutdown();
        assertTrue(executor.awaitTermination(1, TimeUnit.MINUTES));
    }

    @Test
    void testGetAndSet() throws InterruptedException {
        AtomicReference<String> ref = new AtomicReference<>("initial");
        int numberOfThreads = 10;
        ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);

        for (int i = 0; i < numberOfThreads; i++) {
            executor.submit(() -> assertEquals("initial", ref.getAndSet("new")));
        }

        executor.shutdown();
        assertTrue(executor.awaitTermination(1, TimeUnit.MINUTES));
        assertEquals("new", ref.get());
    }

    @Test
    void testGetAndUpdate() throws InterruptedException {
        AtomicReference<Integer> ref = new AtomicReference<>(0);
        int numberOfThreads = 10;
        ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);

        for (int i = 0; i < numberOfThreads; i++) {
            executor.submit(() -> ref.getAndUpdate(x -> x + 1));
        }

        executor.shutdown();
        assertTrue(executor.awaitTermination(1, TimeUnit.MINUTES));
        assertEquals(numberOfThreads, ref.get());
    }

    @Test
    void testUpdateAndGet() throws InterruptedException {
        AtomicReference<Integer> ref = new AtomicReference<>(0);
        int numberOfThreads = 10;
        ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);

        for (int i = 0; i < numberOfThreads; i++) {
            executor.submit(() -> ref.updateAndGet(x -> x + 1));
        }

        executor.shutdown();
        assertTrue(executor.awaitTermination(1, TimeUnit.MINUTES));
        assertEquals(numberOfThreads, ref.get());
    }

    @Test
    void testGetAndAccumulate() throws InterruptedException {
        AtomicReference<Integer> ref = new AtomicReference<>(0);
        int numberOfThreads = 10;
        ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);

        for (int i = 0; i < numberOfThreads; i++) {
            executor.submit(() -> ref.getAndAccumulate(1, Integer::sum));
        }

        executor.shutdown();
        assertTrue(executor.awaitTermination(1, TimeUnit.MINUTES));
        assertEquals(numberOfThreads, ref.get());
    }

    @Test
    void testAccumulateAndGet() throws InterruptedException {
        AtomicReference<Integer> ref = new AtomicReference<>(0);
        int numberOfThreads = 10;
        ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);

        for (int i = 0; i < numberOfThreads; i++) {
            executor.submit(() -> ref.accumulateAndGet(1, Integer::sum));
        }

        executor.shutdown();
        assertTrue(executor.awaitTermination(1, TimeUnit.MINUTES));
        assertEquals(numberOfThreads, ref.get());
    }

    @Test
    void compareSetAndGetPlainWithVolatile() throws InterruptedException {
        AtomicReference<String> ref = new AtomicReference<>("initial");

        // set/get (volatile access)
        ExecutorService executorVolatile = Executors.newFixedThreadPool(2);
        executorVolatile.execute(() -> ref.set("volatileUpdate"));
        executorVolatile.execute(() -> assertEquals("volatileUpdate", ref.get()));
        executorVolatile.shutdown();

        // setPlain/getPlain (non-volatile access)
        AtomicReference<String> refPlain = new AtomicReference<>("initial");
        ExecutorService executorPlain = Executors.newFixedThreadPool(2);
        executorPlain.execute(() -> refPlain.setPlain("plainUpdate"));
        executorPlain.execute(() -> assertEquals("plainUpdate", refPlain.getPlain()));
        executorPlain.shutdown();

        assertTrue(executorVolatile.awaitTermination(1, TimeUnit.SECONDS));
        assertTrue(executorPlain.awaitTermination(1, TimeUnit.SECONDS));
    }

    @Test
    void compareCompareAndSetWithWeakCompareAndSetVolatile() throws InterruptedException {
        AtomicReference<Integer> ref = new AtomicReference<>(0);

        // compareAndSet
        ExecutorService executorCAS = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            executorCAS.submit(() -> {
                while (!ref.compareAndSet(ref.get(), ref.get() + 1)) {
                    // retry
                }
            });
        }

        // weakCompareAndSetVolatile
        AtomicReference<Integer> refWeak = new AtomicReference<>(0);
        ExecutorService executorWeakCAS = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            executorWeakCAS.submit(() -> {
                while (!refWeak.weakCompareAndSetVolatile(refWeak.get(), refWeak.get() + 1)) {
                    // retry
                }
            });
        }

        executorCAS.shutdown();
        executorWeakCAS.shutdown();
        assertTrue(executorCAS.awaitTermination(1, TimeUnit.SECONDS));
        assertTrue(executorWeakCAS.awaitTermination(1, TimeUnit.SECONDS));

        assertEquals(10, ref.get());
        assertEquals(10, refWeak.get());
    }

    @Test
    void compareGetAndSetWithCompareAndExchange() throws InterruptedException {
        AtomicReference<String> ref = new AtomicReference<>("initial");

        // getAndSet
        ExecutorService executorGetAndSet = Executors.newSingleThreadExecutor();
        executorGetAndSet.submit(() -> assertEquals("initial", ref.getAndSet("new")));
        executorGetAndSet.shutdown();

        // compareAndExchange
        AtomicReference<String> refExchange = new AtomicReference<>("initial");
        ExecutorService executorExchange = Executors.newSingleThreadExecutor();
        executorExchange.submit(() -> assertEquals("initial", refExchange.compareAndExchange("initial", "new")));
        executorExchange.shutdown();

        assertTrue(executorGetAndSet.awaitTermination(1, TimeUnit.SECONDS));
        assertTrue(executorExchange.awaitTermination(1, TimeUnit.SECONDS));
        assertEquals("new", ref.get());
        assertEquals("new", refExchange.get());
    }


}
相关文章
|
2月前
|
容器
jdk8新特性-详情查看文档
jdk8新特性-详情查看文档
44 3
|
1月前
|
存储 安全 Java
JDK1.8 新的特性
JDK1.8 新的特性
19 0
|
2月前
|
编解码 安全 Java
jdk8新特性-接口和日期处理
jdk8新特性-接口和日期处理
|
3月前
|
Java API
JDK8到JDK25版本升级的新特性问题之使用Collectors.teeing()来计算一个列表中学生的平均分和总分如何操作
JDK8到JDK25版本升级的新特性问题之使用Collectors.teeing()来计算一个列表中学生的平均分和总分如何操作
|
3月前
|
Java API Apache
JDK8到JDK24版本升级的新特性问题之在Java中,HttpURLConnection有什么局限性,如何解决
JDK8到JDK24版本升级的新特性问题之在Java中,HttpURLConnection有什么局限性,如何解决
|
3月前
|
Oracle Java 关系型数据库
JDK8到JDK29版本升级的新特性问题之未来JDK的升级是否会成为必然趋势,如何理解
JDK8到JDK29版本升级的新特性问题之未来JDK的升级是否会成为必然趋势,如何理解
|
3月前
|
Oracle 安全 Java
JDK8到JDK28版本升级的新特性问题之在Java 15及以后的版本中,密封类和密封接口是怎么工作的
JDK8到JDK28版本升级的新特性问题之在Java 15及以后的版本中,密封类和密封接口是怎么工作的
|
3月前
|
Java API 开发者
JDK8到JDK17版本升级的新特性问题之SpringBoot选择JDK17作为最小支持的Java lts版本意味着什么
JDK8到JDK17版本升级的新特性问题之SpringBoot选择JDK17作为最小支持的Java lts版本意味着什么
121 0
JDK8到JDK17版本升级的新特性问题之SpringBoot选择JDK17作为最小支持的Java lts版本意味着什么
|
2月前
|
Java 编译器 API
JDK8新特性--lambda表达式
JDK8的Lambda表达式是Java语言的一大进步。它为Java程序提供了更多的编程方式,让代码更加简洁,也让函数式编程的概念在Java中得到了体现。Lambda表达式与Java 8的其他新特性,如Stream API、新的日期时间API一起,极大地提高了Java编程的效率和乐趣。随着时间的流逝,Java开发者对这些特性的理解和应用将会越来越深入,进一步推动Java语言和应用程序的发展。
13 0
|
3月前
|
算法 Java iOS开发
JDK8到JDK27版本升级的新特性问题之JDK 17中G1在资源占用方面有何变化
JDK8到JDK27版本升级的新特性问题之JDK 17中G1在资源占用方面有何变化