-
Notifications
You must be signed in to change notification settings - Fork 562
/
LongSequence.java
112 lines (91 loc) · 3.18 KB
/
LongSequence.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/*
* Copyright (c) 2015 The Jupiter Project
*
* Licensed under the Apache License, version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jupiter.common.util;
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
import org.jupiter.common.util.internal.InternalThreadLocal;
/**
* 利用对象继承的内存布局规则来padding避免false sharing, 注意其中对象头会至少占用8个字节
* ---------------------------------------
* For 32 bit JVM:
* _mark : 4 byte constant
* _klass : 4 byte pointer to class
* For 64 bit JVM:
* _mark : 8 byte constant
* _klass : 8 byte pointer to class
* For 64 bit JVM with compressed-oops:
* _mark : 8 byte constant
* _klass : 4 byte pointer to class
* ---------------------------------------
*/
class LongLhsPadding {
@SuppressWarnings("unused")
protected long p01, p02, p03, p04, p05, p06, p07;
}
class LongValue extends LongLhsPadding {
protected volatile long value;
}
class LongRhsPadding extends LongValue {
@SuppressWarnings("unused")
protected long p09, p10, p11, p12, p13, p14, p15;
}
/**
* 序号生成器, 每个线程预先申请一个区间, 步长(step)固定, 以此种方式尽量减少CAS操作,
* 需要注意的是, 这个序号生成器不是严格自增的, 并且也溢出也是可以接受的(接受负数).
*
* jupiter
* org.jupiter.common.util
*
* @author jiachun.fjc
*/
public class LongSequence extends LongRhsPadding {
private static final int DEFAULT_STEP = 128;
private static final AtomicLongFieldUpdater<LongValue> updater = AtomicLongFieldUpdater.newUpdater(LongValue.class, "value");
private final InternalThreadLocal<LocalSequence> localSequence = new InternalThreadLocal<LocalSequence>() {
@Override
protected LocalSequence initialValue() throws Exception {
return new LocalSequence();
}
};
private final int step;
public LongSequence() {
this(DEFAULT_STEP);
}
public LongSequence(int step) {
this.step = step;
}
public LongSequence(long initialValue, int step) {
updater.set(this, initialValue);
this.step = step;
}
public long next() {
return localSequence.get().next();
}
private long getNextBaseValue() {
return updater.getAndAdd(this, step);
}
private final class LocalSequence {
private long localBase = getNextBaseValue();
private long localValue = 0;
public long next() {
long realVal = ++localValue + localBase;
if (localValue == step) {
localBase = getNextBaseValue();
localValue = 0;
}
return realVal;
}
}
}