Java中的LinkedTransferQueue tryTransfer()方法及示例

Java中的LinkedTransferQueue tryTransfer()方法及示例

LinkedTransferQueue 简介

LinkedTransferQueue 是Java中的一个并发容器,继承至AbstractQueue和TransferQueue,它提供了一种线程之间进行数据传递的高效方式。

与其它Queue实现不同的是,LinkedTransferQueue 在处理元素时会自动阻塞线程,直到有一个另外的线程通过take或者poll获取这个元素或者被offer方法成功插入一个元素。

对于连续空间(Location)的take操作,LinkedTransferQueue提供了一个额外的方法tryTransfer,这篇文章就是要详细介绍它。

tryTransfer()方法

tryTransfer可以直接将元素加入到BlockingQueue, 但需要满足一定条件,如果条件不符合,则会直接返回一个boolean值,不会阻塞线程,具体如下:

  • 如果当前有等待获取的线程,则直接返回true,若无等待线程则执行offer操作,若成功则返回true, 否则返回false。

  • 若当前有竞争者线程正在执行take操作, 则直接交由竞争者线程获取数据,那么返回一个false。

  • 若其他线程正在等待入队,则直接将元素入队,等待线程就可以成功获取元素,返回true。

示例:线程池中使用tryTransfer()方法

现在我们考虑一个案例,在一个线程池中使用tryTransfer()方法,每个线程都是准备取出一个任务进行处理,当线程池中有未完成的任务时则尝试使用tryTransfer()方法,添加任务进入线程池,如下所示:

public class LinkedTansferQueueDemo {

    private static LinkedTransferQueue<Integer> linkedTransferQueue = new LinkedTransferQueue<>();

    public static void main(String[] args) {
        int threadCount = 2;
        ExecutorService executorService = Executors.newFixedThreadPool(threadCount);

        for (int i = 0; i < threadCount; i++) {
            executorService.execute(new WaitTask());
            executorService.execute(new Task());
        }
    }

    static class WaitTask implements Runnable {
        @Override
        public void run() {
            try {
                Integer take = linkedTransferQueue.take();
                System.out.println(Thread.currentThread().getName()+" Take : " + take);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    static class Task implements Runnable {
        @Override
        public void run() {
            Random random = new Random();
            try {
                Thread.sleep(random.nextInt(3000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (linkedTransferQueue.hasWaitingConsumer()) {
                System.out.println(Thread.currentThread().getName() + " Transfer : 1");
                boolean b = linkedTransferQueue.tryTransfer(1);
                System.out.println(Thread.currentThread().getName() + " " + b);
            } else {
                try {
                    System.out.println(Thread.currentThread().getName() + " Offer : 2");
                    linkedTransferQueue.offer(2, 300, TimeUnit.MILLISECONDS);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

该示例中,我们创建一个指定线程数的线程池,每个线程分别由WaitTask和Task类来执行。WaitTask类会对linkedTransferQueue进行take操作,如果没有元素,则会阻塞一直等待,直到有元素加入。Task类则会把一个任务加入到线程池中,如果有等待take的线程则直接使用tryTransfer方法把任务加入队列,没有等待take操作的线程则使用offer方法将任务加入队列。

执行结果如下:

pool-1-thread-2 Transfer : 1
pool-1-thread-2 true
pool-1-thread-2 Transfer : 1
pool-1-thread-2 true
pool-1-thread-1 Take : 1
pool-1-thread-1 Take : 1
pool-1-thread-1 Transfer : 1
pool-1-thread-1 true
pool-1-thread-1 Take : 2

从结果中我们可以看出,在没有等待take操作的情况下,Task类使用的是offer方法将任务加入队列。而在有等待take操作的情况下,则直接使用tryTransfer方法将任务加入队列并返回true。

结论

通过本文介绍,我们了解了LinkedTransferQueue的tryTransfer方法及其使用方式。它可以方便地实现多线程之间的数据传递操作,并且使用起来比较简单。当需要快速向一个BlockingQueue中添加一个元素并且希望不会被阻塞时,tryTransfer方法是一个很好的选择。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程