LinkedTransferQueue 使用介绍

LinkedTransferQueue

阻塞方法有:
transfer:调用此方法后要等到有消费者获取此元素之后才返回,不然就一直阻塞。
take和poll: 如果为空就一直阻塞.
另外此队列是无界的。

package com.abc.test;

import com.google.common.base.Stopwatch;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;


/**
 * 注意:以下测试用例只能单独执行.
 */
public class LinkedTransferQueueTest {

    public static class MyElement {
        final int order;
        final String name;

        public MyElement(String name, int order) {
            this.name = name;
            this.order = order;
        }
    }

    LinkedTransferQueue<MyElement> linkedTransferQueue = new LinkedTransferQueue<MyElement>();

    //注意线程池数目不能设置为1个.
    ExecutorService pools = Executors.newFixedThreadPool(4);

    /**
     *
     */
    @Before
    public void init() {
        IntStream.range(0, 10).forEach(value -> {
            linkedTransferQueue.add(new MyElement("" + value, value));
        });
    }

    /**
     *
     */
    @Test
    public void testPoll() {
        Assert.assertNotNull(linkedTransferQueue.poll());
        Assert.assertEquals(linkedTransferQueue.poll().order, 1);
    }

    /**
     * 无界的,可以一直存储到内存溢出.
     */
    @Test(expected = OutOfMemoryError.class)
    public void testUnbounded() {
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            linkedTransferQueue.add(new MyElement("", i));
        }
    }

    /**
     * 清空之后再测试
     * 先启动子线程来take,由于没有元素,因此take会阻塞此线程等待新元素的到来。
     * 在主线程通过transfer等待子线程来接受这个元素,主线程也会阻塞。
     * 子线程增加2秒延时主要是为了延时主线程的transfer方法会阻塞.
     *
     * @throws InterruptedException
     */
    @Test(timeout = 10 * 1000)
    public void testTransfer() throws InterruptedException {
        linkedTransferQueue.clear();
        Stopwatch stopwatch = Stopwatch.createStarted();
        pools.execute(() -> {
            try {
                Thread.sleep(2000);
                MyElement element = linkedTransferQueue.take();
                Assert.assertEquals(element.order, 100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        linkedTransferQueue.transfer(new MyElement("100", 100));
        long duration = stopwatch.stop().elapsed(TimeUnit.MILLISECONDS);
        System.out.println(duration);
        Assert.assertTrue(duration > 2000);
        pools.shutdown();
    }

    /**
     * 没有做清空.
     * 子线程取到的是之前的元素,因此主线程的transfer方法会一直阻塞.
     *
     * @throws InterruptedException
     */
    @Test(timeout = 100 * 1000)
    public void testTransfer2() throws InterruptedException {
        pools.execute(() -> {
            try {
                Thread.sleep(2000);
                MyElement element = linkedTransferQueue.take();
                Assert.assertEquals(element.order, 0);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        linkedTransferQueue.transfer(new MyElement("100", 100));
        pools.shutdown();
    }

}

你可能感兴趣的:(java,java,开发语言,后端)