Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients.
ReferenceCounted
io.netty.util.ReferenceCounted
引用计数文档
public interface ReferenceCounted A reference-counted object that requires explicit deallocation. When a new ReferenceCounted is instantiated, it starts with the reference count of 1. retain() increases the reference count, and release() decreases the reference count. If the reference count is decreased to 0, the object will be deallocated explicitly, and accessing the deallocated object will usually result in an access violation. If an object that implements ReferenceCounted is a container of other objects that implement ReferenceCounted, the contained objects will also be released via release() when the container’s reference count becomes 0.
我们看看其中的方法
publicinterfaceReferenceCounted{ /** * Returns the reference count of this object. If {@code 0}, it means this object has been deallocated. */ intrefCnt();
/** * Increases the reference count by {@code 1}. */ ReferenceCounted retain();
/** * Increases the reference count by the specified {@code increment}. */ ReferenceCounted retain(int increment);
/** * Records the current access location of this object for debugging purposes. * If this object is determined to be leaked, the information recorded by this operation will be provided to you * via {@link ResourceLeakDetector}. This method is a shortcut to {@link #touch(Object) touch(null)}. */ ReferenceCounted touch();
/** * Records the current access location of this object with an additional arbitrary information for debugging * purposes. If this object is determined to be leaked, the information recorded by this operation will be * provided to you via {@link ResourceLeakDetector}. */ ReferenceCounted touch(Object hint);
/** * Decreases the reference count by {@code 1} and deallocates this object if the reference count reaches at * {@code 0}. * * @return {@code true} if and only if the reference count became {@code 0} and this object has been deallocated */ booleanrelease();
/** * Decreases the reference count by the specified {@code decrement} and deallocates this object if the reference * count reaches at {@code 0}. * * @return {@code true} if and only if the reference count became {@code 0} and this object has been deallocated */ booleanrelease(int decrement); }
@Override public ByteBuf retain(){ return retain0(1); }
@Override public ByteBuf retain(int increment){ return retain0(checkPositive(increment, "increment")); }
private ByteBuf retain0(int increment){ for (;;) { int refCnt = this.refCnt; finalint nextCnt = refCnt + increment; // 如果 refCnt = 0 的时候 nextCont = increment,就就应该被回收 // Ensure we not resurrect (which means the refCnt was 0) and also that we encountered an overflow. if (nextCnt <= increment) { thrownew IllegalReferenceCountException(refCnt, increment); } // 这里使用到了自旋锁 if (refCntUpdater.compareAndSet(this, refCnt, nextCnt)) { break; } } returnthis; }
public abstract class AtomicIntegerFieldUpdater extends Object A reflection-based utility that enables atomic updates to designated volatile int fields of designated classes. This class is designed for use in atomic data structures in which several fields of the same node are independently subject to atomic updates. Note that the guarantees of the compareAndSet method in this class are weaker than in other atomic classes. Because this class cannot ensure that all uses of the field are appropriate for purposes of atomic access, it can guarantee atomicity only with respect to other invocations of compareAndSet and set on the same updater.
public abstract boolean compareAndSet(T obj, int expect, int update) Atomically sets the field of the given object managed by this updater to the given updated value if the current value == the expected value. This method is guaranteed to be atomic with respect to other calls to compareAndSet and set, but not necessarily with respect to other changes in the field. Parameters: obj - An object whose field to conditionally set expect - the expected value update - the new value
一个不安全的更新
/** * @Author: cuzz * @Date: 2019/1/19 15:40 * @Description: */ publicclassAtomicUpdateTest{ publicstaticvoidmain(String[] args){ Person person = new Person(); for (int i = 0; i < 10; i++) { new Thread(() -> { try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } System.out.print(person.age++ + " "); // 1 6 7 5 4 2 3 1 8 9 }).start(); }
} } classPerson{ int age = 1; }
使用AtomicIntegerFieldUpdater
/** * @Author: cuzz * @Date: 2019/1/19 15:40 * @Description: */ publicclassAtomicUpdateTest{ publicstaticvoidmain(String[] args){ AtomicIntegerFieldUpdater<Person> fieldUpdater = AtomicIntegerFieldUpdater.newUpdater(Person.class, "age"); Person person = new Person(); for (int i = 0; i < 10; i++) { new Thread(() -> { try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } System.out.print(fieldUpdater.getAndIncrement(person) + " "); // 1 4 3 2 5 6 7 10 9 8 }).start(); } } } classPerson{ volatileint age = 1; }
编写一个解码器在客服端与服务端传输一个 Long 型的数据,Netty 为我们提供了 ByteToMessageDecoder
io.netty.handler.codec.ByteToMessageDecoder
io.netty.handler.codec public abstract class ByteToMessageDecoder extends ChannelInboundHandlerAdapter ChannelInboundHandlerAdapter which decodes bytes in a stream-like fashion from one ByteBuf to an other Message type. For example here is an implementation which reads all readable bytes from the input ByteBuf and create a new ByteBuf. public class SquareDecoder extends ByteToMessageDecoder { @Override public void decode(ChannelHandlerContext ctx, ByteBuf in, List