5.Disruptor

Disruptor

    简介:
        这个系统是建立在JVM平台上,其核心是一个业务逻辑处理器,它能够在一个线程里每秒处理
        6百万订单。业务逻辑处理器完全是运行在内存中,使用事件源驱动方式。业务逻辑处理器的
        核心是Disruptor。
        Disruptor它是一个开源的并发框架,能够在无锁的情况下实现网络的Queue并发操作。
        Disruptor是一个高性能的异步处理框架,或者可以认为是最快的消息框架(轻量的JMS),
                  也可以认为是一个观察者模式的实现,或者事件监听模式的实现。
                  
        在使用之前,首先说明disruptor主要功能加以说明,你可以理解为他是一种高效的
                    "生产者-消费者"模型。也就性能远远高于传统的BlockingQueue容器。
                    
        官方学习网站: http://ifeve.com/disruptor-getting-started/

    在Disruptor中,我们想实现hello world 需要如下几步骤:
        第一:建立一个Event类
        第二:建立一个工厂Event类,用于创建Event类实例对象
        第三:需要有一个监听事件类,用于处理数据(Event类)
        第四:我们需要进行测试代码编写。实例化Disruptor实例,配置一系列参数。
              然后我们对Disruptor实例绑定监听事件类,接受并处理数据。
        第五:在Disruptor中,真正存储数据的核心叫做RingBuffer,我们通过Disruptor实例拿到
              它,然后把数据生产出来,把数据加入到RingBuffer的实例对象中即可。

              
        Disruptor<LongEvent> disruptor = new Disruptor<LongEvent>(factory, ringBufferSize,
                                executor, ProducerType.SINGLE, new YieldingWaitStrategy());
            
            第一个参数为工厂类对象,用于创建一个个的LongEvent,LongEvent是实际的消费数据
            第二个参数为缓存区大小
            第三个参数线程池,进行Disruptor内部的数据接收处理调度
            第四个参数ProducerType.SINGLE表示生产者只有一个
                      ProducerType.MULTI表示有多个生产者
            第五个参数是一个策略:WaitStrategy
            
                BlockingWaitStrategy 是最低效的策略,但其对CPU的消耗最小并且在各种不同
                部署环境中能提供更加一致的性能表现
                 WaitStrategy BLOCKING_WAIT = new BlockingWaitStrategy();
                
                SleepingWaitStrategy 的性能表现跟BlockingWaitStrategy差不多,对CPU的消耗
                也类似,但其对生产者线程的影响最小,适合用于异步日志类似的场景
                WaitStrategy SLEEPING_WAIT = new SleepingWaitStrategy();
                
                YieldingWaitStrategy 的性能是最好的,适合用于低延迟的系统。在要求极高性能且事件
                处理线数小于CPU逻辑核心数的场景中,推荐使用此策略;例如,CPU开启超线程的特性
                WaitStrategy YIELDING_WAIT = new YieldingWaitStrategy();
                
        disruptor.handleEventsWith(new LongEventHandler()) //连接消费事件,
                                    //new LongEventHandler() 消费者  实现EventHandler接口
        disruptor.start(); //启动
        //使用该方法或得具体存放数据的容器ringBuffer(环形结构)
        RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer();
        //将生产者放入容器中
        LongEventProducer producer = new LongEventProducer(ringBuffer);
        disruptor.shutdown();//关闭 disruptor,方法会堵塞,直至所有的事件都得到处理;
        executor.shutdown();//关闭 disruptor 使用的线程池;如果需要的话,必须手动关闭,
                            //disruptor 在 shutdown 时不会自动关闭;

        生产者:
            只有在LongEventProducer类中的onData方法(用来发布事件的方法)中写finally(必须在finally)中
            发布事件后ringBuffer.publish(sequence),才能进行消费事件
            long sequence = ringBuffer.next();//获取下一个事件槽
            
        
简单的程序代码
    基本的事件生产和消费

    我们从一个简单的例子开始学习Disruptor:生产者传递一个long类型的值给消费者,而消费者消费这个数据的方式仅仅是把它打印出来。首先声明一个Event来包含需要传递的数据:

    public class LongEvent {
        private long value;
        public long getValue() {
            return value;
        }
    
        public void setValue(long value) {
            this.value = value;
        }
    }

    由于需要让Disruptor为我们创建事件,我们同时还声明了一个EventFactory来实例化Event对象。

    public class LongEventFactory implements EventFactory {

        @Override
        public Object newInstance() {
            return new LongEvent();
        }
    }

    我们还需要一个事件消费者,也就是一个事件处理器。这个事件处理器简单地把事件中存储的数据打印到终端:

    /**
     */public class LongEventHandler implements EventHandler<LongEvent> {
        @Override
        public void onEvent(LongEvent longEvent, long l, boolean b) throws Exception {
            System.out.println(longEvent.getValue());
        }
    }

    事件都会有一个生成事件的源,这个例子中假设事件是由于磁盘IO或者network读取数据的时候触发的,事件源使用一个ByteBuffer来模拟它接受到的数据,也就是说,事件源会在IO读取到一部分数据的时候触发事件(触发事件不是自动的,程序员需要在读取到数据的时候自己触发事件并发布):

    

    public class LongEventProducer {
        private final RingBuffer<LongEvent> ringBuffer;
        public LongEventProducer(RingBuffer<LongEvent> ringBuffer) {
            this.ringBuffer = ringBuffer;
        }
    
        /**
         * onData用来发布事件,每调用一次就发布一次事件事件
         * 它的参数会通过事件传递给消费者
         *
         * @param bb
         */public void onData(ByteBuffer bb) {
                //可以把ringBuffer看做一个事件队列,那么next就是得到下面一个事件槽
                long sequence = ringBuffer.next();try {
                //用上面的索引取出一个空的事件用于填充
                LongEvent event = ringBuffer.get(sequence);// for the sequence
                event.setValue(bb.getLong(0));
            } finally {
                //发布事件
                ringBuffer.publish(sequence);
            }
        }
    }

    很明显的是:当用一个简单队列来发布事件的时候会牵涉更多的细节,这是因为事件对象还需要预先创建。发布事件最少需要两步:获取下一个事件槽并发布事件(发布事件的时候要使用try/finnally保证事件一定会被发布)。如果我们使用RingBuffer.next()获取一个事件槽,那么一定要发布对应的事件。如果不能发布事件,那么就会引起Disruptor状态的混乱。尤其是在多个事件生产者的情况下会导致事件消费者失速,从而不得不重启应用才能会恢复。

    Disruptor 3.0提供了lambda式的API。这样可以把一些复杂的操作放在Ring Buffer,所以在Disruptor3.0以后的版本最好使用Event Publisher或者Event Translator来发布事件。

    

    public class LongEventProducerWithTranslator {
        //一个translator可以看做一个事件初始化器,publicEvent方法会调用它
        //填充Event
        private static final EventTranslatorOneArg<LongEvent, ByteBuffer> TRANSLATOR =
                new EventTranslatorOneArg<LongEvent, ByteBuffer>() {
                    public void translateTo(LongEvent event, long sequence, ByteBuffer bb) {
                        event.setValue(bb.getLong(0));
                    }
                };
        private final RingBuffer<LongEvent> ringBuffer;
        public LongEventProducerWithTranslator(RingBuffer<LongEvent> ringBuffer) {
            this.ringBuffer = ringBuffer;
        }
    
        public void onData(ByteBuffer bb) {
            ringBuffer.publishEvent(TRANSLATOR, bb);
        }
    }

    上面写法的另一个好处是,Translator可以分离出来并且更加容易单元测试。Disruptor提供了不同的接口(EventTranslator, EventTranslatorOneArg, EventTranslatorTwoArg, 等等)去产生一个Translator对象。很明显,Translator中方法的参数是通过RingBuffer来传递的。

    

    最后一步就是把所有的代码组合起来完成一个完整的事件处理系统。Disruptor在这方面做了简化,使用了DSL风格的代码(其实就是按照直观的写法,不太能算得上真正的DSL)。虽然DSL的写法比较简单,但是并没有提供所有的选项。如果依靠DSL已经可以处理大部分情况了。

    

    public class LongEventMain {
        public static void main(String[] args) throws InterruptedException {
            // Executor that will be used to construct new threads for consumers
            Executor executor = Executors.newCachedThreadPool();
            // The factory for the event
            LongEventFactory factory = new LongEventFactory();
            // Specify the size of the ring buffer, must be power of 2.
            int bufferSize = 1024;
            // Construct the Disruptor
            Disruptor<LongEvent> disruptor = new Disruptor<LongEvent>(factory, bufferSize, executor);
            // Connect the handler
            disruptor.handleEventsWith(new LongEventHandler());
            // Start the Disruptor, starts all threads running
            disruptor.start();
            // Get the ring buffer from the Disruptor to be used for publishing.
            RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer();
    
            LongEventProducer producer = new LongEventProducer(ringBuffer);
    
            ByteBuffer bb = ByteBuffer.allocate(8);
            for (long l = 0; true; l++) {
                bb.putLong(0, l);
                producer.onData(bb);
                Thread.sleep(1000);
            }
        }
    }

Disruptor术语说明

    RingBuffer:仅仅负责存储和更新在Disruptor中流通的数据。
    
    Sequence:Disruptor使用Sequence来表示一个特殊组件处理的序号。每个消费者(EventProcessor)
            都维持着一个Sequence。大部分的并发代码依赖这些Sequence值得运转,Sequence支持多种
            当前为AtomicLong类的特性
    
    Sequencer: 这是Disruptor真正的核心。实现了这个接口的两种生产者(单生产者和多生产者)
            均实现了所有的并发算法,为了在生产者和消费者之间进行准确快速的数据传递。
            
    SequenceBarrier: 由Sequencer生成,并且包含了已经发布的Sequence的引用,这些的Sequence源于
                    Sequencer和一些独立的消费者的Sequence。它包含了决定是否有供消费者来消费
                    的Event的逻辑
    
    WaitStrategy:决定一个消费者将如何等待生产者将Event置入Disruptor。
    
    Event:从生产者到消费者过程中所处理的数据单元。Disruptor中没有代码表示Event,因为它完全
           是由用户定义的。
           
    EventProcessor:主要事件循环,处理Disruptor中的Event,并且拥有消费者的Sequence。它有一个
                    实现类是BatchEventProcessor,包含了event loop有效的实现,并且将回调到一个
                    EventHandler接口的实现对象。
                    
    EventHandler:由用户实现并且代表了Disruptor中的一个消费者的接口。
    
    Producer:由用户实现,它调用RingBuffer来插入事件(Event),在Disruptor中没有相应的实现
              代码,由用户实现。
              
    WorkProcessor:确保每个sequence只被一个processor消费,在同一个WorkPool中的处理多个
                   WorkProcessor不会消费同样的sequence。
                   
    WorkerPool:一个WorkProcessor池,其中WorkProcessor将消费Sequence,所以任务可以在
                实现WorkHandler接口的worker吃间移交
                
    LifecycleAware:当BatchEventProcessor启动和停止时,于实现这个接口用于接收通知。

    
初看Disruptor,给人的印象就是RingBuffer是其核心,生产者向RingBuffer中写入元素,
消费者从RingBuffer中消费元素。

ringbuffer到底是什么?
    答:嗯,正如名字所说的一样,它是一个环(首尾相接的环2的n次方),你可以把它用做在不同
        上下文(线程)间传递数据的buffer。
        基本来说,ringbuffer拥有一个序号,这个序号指向数组中下一个可用元素。
        

其实在很多时候我们可以直接使用RIngBuffer,处理简单的,简单环境下的,处理结果比较单一
如果处理环状的使用Disruptor,内部处理如菱形,六角形等,就是同时执行两个,执行一个之后再执行等
    
    1,使用EventProcessor消息处理器
    
        主线程类
        public class Main1 {  
       
            public static void main(String[] args) throws Exception {  
                int BUFFER_SIZE=1024;  
                int THREAD_NUMBERS=4;  
                /*
                 * createSingleProducer创建一个单生产者的RingBuffer,
                 * 第一个参数叫EventFactory,从名字上理解就是"事件工厂",其实它的职责就是产生数据填充RingBuffer的区块。
                 * 第二个参数是RingBuffer的大小,它必须是2的指数倍 目的是为了将求模运算转为&运算提高效率
                 * 第三个参数是RingBuffer的生产都在没有可用区块的时候(可能是消费者(或者说是事件处理器) 太慢了)的等待策略
                 */  
                final RingBuffer<Trade> ringBuffer = RingBuffer.createSingleProducer(new EventFactory<Trade>() {  
                    @Override  
                    public Trade newInstance() {  
                        return new Trade();  
                    }  
                }, BUFFER_SIZE, new YieldingWaitStrategy());  
                
                //创建线程池  
                ExecutorService executors = Executors.newFixedThreadPool(THREAD_NUMBERS);  
                
                //创建SequenceBarrier  
                SequenceBarrier sequenceBarrier = ringBuffer.newBarrier();  
                  
                //创建消息处理器  
                BatchEventProcessor<Trade> transProcessor = new BatchEventProcessor<Trade>(  
                        ringBuffer, sequenceBarrier, new TradeHandler());  
                  
                //这一步的目的就是把消费者的位置信息引用注入到生产者    如果只有一个消费者的情况可以省略
                ringBuffer.addGatingSequences(transProcessor.getSequence());  
                  
                //把消息处理器提交到线程池  
                executors.submit(transProcessor);  
                
                //如果存在多个消费者 那重复执行上面3行代码 把TradeHandler换成其它消费者类  
                //这里也可以直接写for循环,也可以用Future实现
                Future<?> future= executors.submit(new Callable<Void>() {  
                    @Override  
                    public Void call() throws Exception {  
                        long seq;  
                        for(int i=0;i<10;i++){  
                            seq = ringBuffer.next();//占个坑 --ringBuffer一个可用区块  
                            ringBuffer.get(seq).setPrice(Math.random()*9999);//给这个区块放入 数据
                            ringBuffer.publish(seq);//发布这个区块的数据使handler(consumer)可见  
                        }  
                        return null;  
                    }  
                });
                
                future.get();//等待生产者结束  
                Thread.sleep(1000);//等上1秒,等消费都处理完成  
                transProcessor.halt();//通知事件(或者说消息)处理器 可以结束了(并不是马上结束!!!)  
                executors.shutdown();//终止线程  
            }  
        }
        
        消费者类
        public class TradeHandler implements EventHandler<Trade>, WorkHandler<Trade> {  
          
            @Override  
            public void onEvent(Trade event, long sequence, boolean endOfBatch) throws Exception {  
                this.onEvent(event);  
            }  
          
            @Override  
            public void onEvent(Trade event) throws Exception {  
                //这里做具体的消费逻辑  
                event.setId(UUID.randomUUID().toString());//简单生成下ID  
                System.out.println(event.getId()+"---"+event.getPrice());
            }  
        }

        消费的事件,数据
        public class Trade {  
            private String id;//ID  
            private String name;
            private double price;//金额  
            private AtomicInteger count = new AtomicInteger(0);
            
            public String getId() {
                return id;
            }
            public void setId(String id) {
                this.id = id;
            }
            public String getName() {
                return name;
            }
            public void setName(String name) {
                this.name = name;
            }
            public double getPrice() {
                return price;
            }
            public void setPrice(double price) {
                this.price = price;
            }
            public AtomicInteger getCount() {
                return count;
            }
            public void setCount(AtomicInteger count) {
                this.count = count;
            }
        }
    
    2,使用WorkerPool消息处理器
    public class Main2 {  
        public static void main(String[] args) throws InterruptedException {  
            int BUFFER_SIZE=1024;  
            int THREAD_NUMBERS=4;  
            
            EventFactory<Trade> eventFactory = new EventFactory<Trade>() {  
                public Trade newInstance() {  
                    return new Trade();  
                }  
            };  
            
            RingBuffer<Trade> ringBuffer = RingBuffer.createSingleProducer(eventFactory, BUFFER_SIZE);  
              
            SequenceBarrier sequenceBarrier = ringBuffer.newBarrier();  
              
            ExecutorService executor = Executors.newFixedThreadPool(THREAD_NUMBERS);  
              
            WorkHandler<Trade> handler = new TradeHandler();  

            WorkerPool<Trade> workerPool = new WorkerPool<Trade>(ringBuffer, sequenceBarrier, new IgnoreExceptionHandler(), handler);  
              
            workerPool.start(executor);  
              
            //下面这个生产8个数据
            for(int i=0;i<8;i++){  
                long seq=ringBuffer.next();  
                ringBuffer.get(seq).setPrice(Math.random()*9999);  
                ringBuffer.publish(seq);  
            }  
              
            Thread.sleep(1000);  
            workerPool.halt();  
            executor.shutdown();  
        }  
    }
    
    
应用场景

    多个消费者,一个生产者
        public class Main {  
            public static void main(String[] args) throws InterruptedException {  
                long beginTime=System.currentTimeMillis();  
                int bufferSize=1024;  
                ExecutorService executor=Executors.newFixedThreadPool(8);  

                Disruptor<Trade> disruptor = new Disruptor<Trade>(new EventFactory<Trade>() {  
                    @Override  
                    public Trade newInstance() {  
                        return new Trade();  
                    }  
                }, bufferSize, executor, ProducerType.SINGLE, new BusySpinWaitStrategy());  
                
                //菱形操作            
                //使用disruptor创建消费者组C1,C2  
                EventHandlerGroup<Trade> handlerGroup =
                        disruptor.handleEventsWith(new Handler1(), new Handler2());
                //声明在C1,C2完事之后执行JMS消息发送操作 也就是流程走到C3
                handlerGroup.then(new Handler3());
                */
                
                //顺序操作
                /**
                disruptor.handleEventsWith(new Handler1()).
                    handleEventsWith(new Handler2()).
                    handleEventsWith(new Handler3());
                */
                
                //六边形操作.
                /**
                Handler1 h1 = new Handler1();
                Handler2 h2 = new Handler2();
                Handler3 h3 = new Handler3();
                Handler4 h4 = new Handler4();
                Handler5 h5 = new Handler5();
                disruptor.handleEventsWith(h1, h2);
                disruptor.after(h1).handleEventsWith(h4);
                disruptor.after(h2).handleEventsWith(h5);
                disruptor.after(h4, h5).handleEventsWith(h3);
                */

                disruptor.start();//启动  
                CountDownLatch latch=new CountDownLatch(1);  
                //生产者准备  
                executor.submit(new TradePublisher(latch, disruptor));
                
                latch.await();//等待生产者完事.
               
                disruptor.shutdown();  
                executor.shutdown();  
                System.out.println("总耗时:"+(System.currentTimeMillis()-beginTime));  
            }  
        }  
        
        
        public class TradePublisher implements Runnable {  
            Disruptor<Trade> disruptor;  
            private CountDownLatch latch;  
            
            private static int LOOP=10;//模拟百万次交易的发生  
          
            public TradePublisher(CountDownLatch latch,Disruptor<Trade> disruptor) {  
                this.disruptor=disruptor;  
                this.latch=latch;  
            }  
          
            @Override  
            public void run() {  
                TradeEventTranslator tradeTransloator = new TradeEventTranslator();  
                for(int i=0;i<LOOP;i++){  
                    disruptor.publishEvent(tradeTransloator);  
                }  
                latch.countDown();  
            }  
              
        }  
          
        class TradeEventTranslator implements EventTranslator<Trade>{  
            
            private Random random=new Random();  
            
            @Override  
            public void translateTo(Trade event, long sequence) {  
                this.generateTrade(event);  
            }  
            
            private Trade generateTrade(Trade trade){  
                trade.setPrice(random.nextDouble()*9999);  
                return trade;  
            }  
            
        }  
        //Handler
        public class Handler5 implements EventHandler<Trade>,WorkHandler<Trade> {  
            @Override  
            public void onEvent(Trade event, long sequence, boolean endOfBatch) throws Exception {  
                this.onEvent(event);  
            }  
          
            @Override  
            public void onEvent(Trade event) throws Exception {  
                System.out.println("handler5: get price : " + event.getPrice());
                event.setPrice(event.getPrice() + 3.0);
            }  
        }  
        public class Handler4 implements EventHandler<Trade>,WorkHandler<Trade> {        
            @Override  
            public void onEvent(Trade event, long sequence, boolean endOfBatch) throws Exception {  
                this.onEvent(event);  
            }  
          
            @Override  
            public void onEvent(Trade event) throws Exception {  
                System.out.println("handler4: get name : " + event.getName());
                event.setName(event.getName() + "h4");
            }  
        }
        public class Handler3 implements EventHandler<Trade> {
            @Override  
            public void onEvent(Trade event, long sequence,  boolean endOfBatch) throws Exception {  
                System.out.println("handler3: name: " + event.getName() + " , price: " + event.getPrice() + ";  instance: " + event.toString());
            }  
        }
        public class Handler2 implements EventHandler<Trade> {  
            @Override  
            public void onEvent(Trade event, long sequence,  boolean endOfBatch) throws Exception {  
                System.out.println("handler2: set price");
                event.setPrice(17.0);
                Thread.sleep(1000);
            }  
        }
        public class Handler1 implements EventHandler<Trade>,WorkHandler<Trade> {  
            @Override  
            public void onEvent(Trade event, long sequence, boolean endOfBatch) throws Exception {  
                this.onEvent(event);  
            }  
            @Override  
            public void onEvent(Trade event) throws Exception {  
                System.out.println("handler1: set name");
                event.setName("h1");
                Thread.sleep(1000);
            }  
        }
    
    多生产者、消费者使用
    public class Main {
        public static void main(String[] args) throws Exception {
            //创建ringBuffer
            RingBuffer<Order> ringBuffer =
                    RingBuffer.create(ProducerType.MULTI,
                            new EventFactory<Order>() {  
                                @Override  
                                public Order newInstance() {  
                                    return new Order();  
                                }  
                            },
                            1024 * 1024,
                            new YieldingWaitStrategy());
            
            SequenceBarrier barriers = ringBuffer.newBarrier();
            
            Consumer[] consumers = new Consumer[3];
            for(int i = 0; i < consumers.length; i++){
                consumers[i] = new Consumer("c" + i);
            }
            
            WorkerPool<Order> workerPool =
                    new WorkerPool<Order>(ringBuffer,
                            barriers,
                            new IntEventExceptionHandler(),
                            consumers);
            
            ringBuffer.addGatingSequences(workerPool.getWorkerSequences());  
            workerPool.start(Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()));  
            
            final CountDownLatch latch = new CountDownLatch(1);
            for (int i = 0; i < 100; i++) {  
                final Producer p = new Producer(ringBuffer);
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            latch.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        for(int j = 0; j < 100; j ++){
                            p.onData(UUID.randomUUID().toString());
                        }
                    }
                }).start();
            }
            Thread.sleep(2000);
            System.out.println("---------------开始生产-----------------");
            latch.countDown();
            Thread.sleep(5000);
            System.out.println("总数:" + consumers[0].getCount() );
        }
        
        static class IntEventExceptionHandler implements ExceptionHandler {  
            public void handleEventException(Throwable ex, long sequence, Object event) {}  
            public void handleOnStartException(Throwable ex) {}  
            public void handleOnShutdownException(Throwable ex) {}  
        }
    }
    
    public class Consumer implements WorkHandler<Order>{
        
        private String consumerId;
        
        private static AtomicInteger count = new AtomicInteger(0);
        
        public Consumer(String consumerId){
            this.consumerId = consumerId;
        }

        @Override
        public void onEvent(Order order) throws Exception {
            System.out.println("当前消费者: " + this.consumerId + ",消费信息:" + order.getId());
            count.incrementAndGet();
        }
        
        public int getCount(){
            return count.get();
        }
    }
    
    public class Order{
        private String id;//ID  
        private String name;
        private double price;//金额
        get()set()
    }
    
    public class Producer {
        private final RingBuffer<Order> ringBuffer;
        
        public Producer(RingBuffer<Order> ringBuffer){
            this.ringBuffer = ringBuffer;
        }
        
        /**
         * onData用来发布事件,每调用一次就发布一次事件
         * 它的参数会用过事件传递给消费者
         */
        public void onData(String data){
            //可以把ringBuffer看做一个事件队列,那么next就是得到下面一个事件槽
            long sequence = ringBuffer.next();
            try {
                //用上面的索引取出一个空的事件用于填充(获取该序号对应的事件对象)
                Order order = ringBuffer.get(sequence);
                //获取要通过事件传递的业务数据
                order.setId(data);
            } finally {
                //发布事件
                //注意,最后的 ringBuffer.publish 方法必须包含在 finally 中以确保必须得到调用;如果某个请求的 sequence 未被提交,将会堵塞后续的发布操作或者其它的 producer。
                ringBuffer.publish(sequence);
            }
        }
            
    }
    
    
    

    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
[JAVA工程师必会知识点之并发编程]1、现在几乎100%的公司面试都必须面试并发编程,尤其是互联网公司,对于并发编程的要求更高,并发编程能力已经成为职场敲门砖。2、现在已经是移动互联和大数据时代,对于应用程序的性能、处理能力、处理时效性要求更高了,传统的串行化编程无法充分利用现有的服务器性能。3、并发编程是几乎所有框架的底层基础,掌握好并发编程更有利于我们学习各种框架。想要让自己的程序执行、接口响应、批处理效率更高,必须使用并发编程。4、并发编程是中高级程序员的标配,是拿高薪的必备条件。 【主讲讲师】尹洪亮Kevin:现任职某互联网公司首席架构师,负责系统架构、项目群管理、产品研发工作。10余年软件行业经验,具有数百个线上项目实战经验。擅长JAVA技术栈、高并发高可用伸缩式微服务架构、DevOps。主导研发的蜂巢微服务架构已经成功支撑数百个微服务稳定运行【推荐你学习这门课的理由:知识体系完整+丰富学习资料】1、 本课程总计122课时,由五大体系组成,目的是让你一次性搞定并发编程。分别是并发编程基础、进阶、精通篇、Disruptor高并发框架、RateLimiter高并发访问限流吗,BAT员工也在学。2、课程附带附带3个项目源码,几百个课程示例,5个高清PDF课件。3、本课程0基础入门,从进程、线程、JVM开始讲起,每一个章节只专注于一个知识点,每个章节均有代码实例。 【课程分为基础篇、进阶篇、高级篇】一、基础篇基础篇从进程与线程、内存、CPU时间片轮训讲起,包含线程的3种创建方法、可视化观察线程、join、sleep、yield、interrupt,Synchronized、重入锁、对象锁、类锁、wait、notify、线程上下文切换、守护线程、阻塞式安全队列等内容。二、进阶篇进阶篇课程涵盖volatied关键字、Actomic类、可见性、原子性、ThreadLocal、Unsafe底层、同步类容器、并发类容器、5种并发队列、COW容器、InheritableThreadLocal源码解析等内容。三、精通篇精通篇课程涵盖JUC下的核心工具类,CountDownLath、CyclicBarrier、Phaser、Semaphore、Exchanger、ReentrantLock、ReentrantReadWriteLock、StampedLock、LockSupport、AQS底层、悲观锁、乐观锁、自旋锁、公平锁、非公平锁、排它锁、共享锁、重入锁、线程池、CachedThreadPool、FixedThreadPool、ScheduledThreadPool、SingleThreadExecutor、自定义线程池、ThreadFactory、线程池切面编程、线程池动态管理等内容,高并发设计模式,Future模式、Master Worker模式、CompletionService、ForkJoin等课程中还包含Disruptor高并发无锁框架讲解:Disruptor支持每秒600万订单处理的恐怖能力。深入到底层原理和开发模式,让你又懂又会用。高并发访问限流讲解:涵盖木桶算法、令牌桶算法、Google RateLimiter限流开发、Apache JMeter压力测试实战。 【学完后我将达到什么水平?】1、 吊打一切并发编程相关的笔试题、面试题。2、 重构自己并发编程的体系知识,不再谈并发色变。3、 精准掌握JAVA各种并发工具类、方法、关键字的原理和使用。4、 轻松上手写出更高效、更优雅的并发程序,在工作中能够提出更多的解决方案。  【面向人群】1、 总感觉并发编程很难、很复杂、不敢学习的人群。2、 准备跳槽、找工作、拿高薪的程序员。3、 希望提高自己的编程能力,开发出更高效、性能更强劲系统的人群。4、 想要快速、系统化、精准掌握并发编程的人群。【课程知识体系图】

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值