Java Sequence Generator examples

摘要: An example to show you how to create a thread safe sequence generator.

An example to show you how to create a thread safe sequence generator.

1. SequenceGenerator

SequenceGenerator.java
package com.mkyong.concurrency.examples.sequence.generator;
public interface SequenceGenerator {
    long getNext();

1.1 First try, read, add, write the value directly. Below method is not thread safe, multiple threads may get the same value at the same time.

UnSafeSequenceGenerator.java
package com.mkyong.concurrency.examples.sequence.generator;
public class UnSafeSequenceGenerator implements SequenceGenerator {
    private long value = 1;
    @Override
    public long getNext() {
        return value++;

1.2 To fix this, make the getNext() as a synchronized method.

SyncSequenceGenerator.java
package com.mkyong.concurrency.examples.sequence.generator;
public class SyncSequenceGenerator implements SequenceGenerator {
    private long value = 1;
    @Override
    public synchronized long getNext() {
        return value++;

1.3 The better solution is using the concurrent.atomic classes, for example AtomicLong

AtomicSequenceGenerator.java
package com.mkyong.concurrency.examples.sequence.generator;
import java.util.concurrent.atomic.AtomicLong;
public class AtomicSequenceGenerator implements SequenceGenerator {
    private AtomicLong value = new AtomicLong(1);
    @Override
    public long getNext() {
        return value.getAndIncrement();

2. Concurrent Access

Simulate a concurrent access environment to test the above sequence generator.

2.1. A Callable task to access the sequence 10 time.

PrintSequenceCallable.java
package com.mkyong.concurrency.examples.sequence;
import com.mkyong.concurrency.examples.sequence.generator.SequenceGenerator;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
public class PrintSequenceCallable implements Callable<List<Long>> {
    private SequenceGenerator sequenceGenerator;
    public PrintSequenceCallable(SequenceGenerator sequenceGenerator) {
        this.sequenceGenerator = sequenceGenerator;
    @Override
    public List<Long> call() throws Exception {
        List<Long> ids = new ArrayList<>();
        for (int i = 1; i <= 10; i++) {
            Thread.sleep(100); //take a nap
            ids.add(sequenceGenerator.getNext());
        return ids;
    };

2.2 Start 3 threads to test the sequence generator.

Main.java
package com.mkyong.concurrency.examples.sequence;
import com.mkyong.concurrency.examples.sequence.generator.SequenceGenerator;
import com.mkyong.concurrency.examples.sequence.generator.UnSafeSequenceGenerator;
import java.util.List;
import java.util.concurrent.*;
public class Main {
    public static void main(String[] args) {
        SequenceGenerator sequenceGenerator = new UnSafeSequenceGenerator();
        //SequenceGenerator sequenceGenerator = new SyncSequenceGenerator();
        //SequenceGenerator sequenceGenerator = new AtomicSequenceGenerator();
        ExecutorService executor = Executors.newCachedThreadPool();
        try {
			// simulate 3 threads concurrent access the sequence generator
            Callable<List<Long>> task1 = new PrintSequenceCallable(sequenceGenerator);
            Callable<List<Long>> task2 = new PrintSequenceCallable(sequenceGenerator);
            Callable<List<Long>> task3 = new PrintSequenceCallable(sequenceGenerator);
            Future f1 = executor.submit(task1);
            Future f2 = executor.submit(task2);
            Future f3 = executor.submit(task3);
            System.out.println(f1.get());
            System.out.println(f2.get());
            System.out.println(f3.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } finally {
            executor.shutdown();

Output

2.2.1 UnSafeSequenceGenerator - Aka race condition, multiple threads is getting the same value, this is not what we want.

[3, 5, 6, 7, 8, 10, 12, 15, 16, 17]
[2, 4, 6, 7, 8, 9, 13, 15, 16, 17]
[1, 4, 6, 7, 8, 11, 14, 15, 16, 17]

2.2.2 SyncSequenceGenerator - Thread safe.

[3, 6, 8, 10, 14, 17, 21, 24, 27, 29]
[1, 4, 9, 12, 15, 18, 20, 22, 25, 30]
[2, 5, 7, 11, 13, 16, 19, 23, 26, 28]

2.2.3 AtomicSequenceGenerator - Thread safe.

[3, 6, 8, 12, 13, 18, 19, 22, 27, 29]
[2, 5, 7, 10, 14, 17, 20, 24, 26, 30]
[1, 4, 9, 11, 15, 16, 21, 23, 25, 28]

Both synchronized and AtomicLong are able to create a thread safe sequence generator. However, the synchronized method is expensive, it will increase the performance cost, the recommended way is using the concurrent.atomic classes like AtomicLong, the atomic classes are designed for concurrent use.

References

  1. Synchronized Methods
  2. Atomic Variables
  3. Why are synchronize expensive in Java?
  4. Race Condition

上一篇: Java Semaphore examples
下一篇: Java ExecutorService examples
 评论 ( What Do You Think )
名称
邮箱
网址
评论
验证
   
 

 


  • 微信公众号

  • 我的微信

站点声明:

1、一号门博客CMS,由Python, MySQL, Nginx, Wsgi 强力驱动

2、部分文章或者资源来源于互联网, 有时候很难判断是否侵权, 若有侵权, 请联系邮箱:summer@yihaomen.com, 同时欢迎大家注册用户,主动发布无版权争议的 文章/资源.

3、鄂ICP备14001754号-3, 鄂公网安备 42280202422812号