java并发编程工具类JUC之LinkedBlockingQueue链表队列

Java并发编程工具类JUC中,LinkedBlockingQueue是一种基于链表的阻塞队列。它可以支持多线程并发访问,是用于多线程交换数据的缓冲区。下面详细讲解一下该队列的使用方法。

LinkedBlockingQueue的特点和操作方法

特点

LinkedBlockingQueue内部采用了一种“等待-通知”机制,当试图向队列中添加元素时,如果队列已满,就会阻塞等待;当试图从队列中取出元素时,如果队列为空,就会阻塞等待。

操作方法

LinkedBlockingQueue的操作方法与其他队列相似,主要有以下方法:

  • put(E e): 添加一个元素,如果队列满,则阻塞等待
  • take(): 取出并删除队列的头元素,如果队列为空,则阻塞等待
  • offer(E e): 添加一个元素,如果队列已满,则返回false,否则返回true
  • poll(): 取出并删除队列的头元素,如果队列为空,则返回null
  • size(): 返回队列元素个数

LinkedBlockingQueue示例

示例一:线程池任务队列

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Main {
    public static void main(String[] args) {
        // 创建一个线程池,最多可以同时执行2个线程
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2, 2, 0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(5)
        );

        // 向线程池提交10个任务
        for (int i = 0; i < 10; i++) {
            executor.execute(new MyTask(String.valueOf(i)));
        }

        // 关闭线程池
        executor.shutdown();
    }
}

class MyTask implements Runnable {
    private String name;

    public MyTask(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " start: " + name);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " end: " + name);
    }
}

在这个示例中,我们创建了一个线程池,使用了LinkedBlockingQueue来作为任务队列,设置了队列的容量为5。向线程池中提交了10个任务,线程池最多可以同时执行2个线程,当任务队列中元素数量达到5时,将不再接受新的任务,直到有线程执行完任务后才会把队列中的元素移除,这样就避免了任务过多导致内存溢出的情况。其中,MyTask实现了Runnable接口,任务执行完毕后打印出线程名称和任务名称。

示例二:多生产者多消费者模型

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class Main {
    public static void main(String[] args) {
        // 创建一个队列,最多可以存放5个元素
        BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(5);

        // 启动3个生产者线程
        for (int i = 1; i <= 3; i++) {
            new Producer(queue, i).start();
        }

        // 启动2个消费者线程
        for (int i = 1; i <= 2; i++) {
            new Consumer(queue, i).start();
        }
    }
}

class Producer extends Thread {
    private final BlockingQueue<Integer> queue;
    private final int num;

    public Producer(BlockingQueue<Integer> queue, int num) {
        this.queue = queue;
        this.num = num;
    }

    @Override
    public void run() {
        try {
            while (true) {
                int i = (int) (Math.random() * 100);
                queue.put(i);
                System.out.println("Producer " + num + " puts: " + i);
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class Consumer extends Thread {
    private final BlockingQueue<Integer> queue;
    private final int num;

    public Consumer(BlockingQueue<Integer> queue, int num) {
        this.queue = queue;
        this.num = num;
    }

    @Override
    public void run() {
        try {
            while (true) {
                int i = queue.take();
                System.out.println("Consumer " + num + " takes: " + i);
                Thread.sleep(2000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

在这个示例中,我们创建了一个容量为5的阻塞队列,启动了3个生产者线程和2个消费者线程,生产者线程不断生成随机数并将其放入队列中,消费者线程不断从队列中取出元素并打印出来。由于队列的容量限制,当队列中元素已满时,生产者线程将会被阻塞,直到队列中有元素被消费掉,才有可能继续向队列中添加元素;当队列为空时,消费者线程将会被阻塞,直到队列中有元素被添加到队列中,才有可能从队列中取出元素。通过这种方式,多个生产者线程和多个消费者线程可以高效地并发访问队列。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java并发编程工具类JUC之LinkedBlockingQueue链表队列 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • 关于SpringBoot 使用 Redis 分布式锁解决并发问题

    关于SpringBoot使用Redis分布式锁解决并发问题的攻略可以分为以下几个步骤: 第一步:引入Redis相关依赖 在开发SpringBoot应用时,我们需要在pom.xml文件中添加对Redis的支持,可以参考下面的依赖: <dependency> <groupId>org.springframework.boot</gr…

    多线程 2023年5月16日
    00
  • Java多线程实现Runnable方式

    Java多线程实现Runnable方式是一种比继承Thread类更加实用、更加灵活的多线程编程方式。下面是Java多线程实现Runnable方式的完整攻略。 1. 实现Runnable接口 要实现Runnable接口,需要创建具体实现了Runnable接口的类并实现run方法。这个run方法就是我们所说的线程执行体,是真正我们需要在线程中执行的代码。 pub…

    多线程 2023年5月17日
    00
  • Linux之线程的创建方式

    下面详细讲解Linux线程的创建方式。 创建线程的方式 在Linux中,我们可以通过pthread库来创建线程,其中比较常用的三种方式分别是: 使用pthread_create函数来创建线程。 使用fork函数创建进程,然后使用pthread_create函数在新进程中创建线程。 使用clone系统调用来创建线程。 下面分别对这三种方式进行详细说明。 使用p…

    多线程 2023年5月16日
    00
  • 浅谈Html5多线程开发之WebWorkers

    浅谈Html5多线程开发之WebWorkers 什么是WebWorkers WebWorkers是HTML5推出的一项新技术,用于JavaScript多线程开发。在WebWorkers API中,定义了两种类型的Worker:DedicatedWorker 和SharedWorker。其中,DedicatedWorker只能被一个页面使用,而SharedWo…

    多线程 2023年5月17日
    00
  • C#多线程系列之线程通知

    C#多线程系列之线程通知主要涵盖三个部分:Monitor、AutoResetEvent和ManualResetEvent。 Monitor 在C#中,Monitor类是一种基本的同步机制,支持两种操作:Enter()和Exit()。Enter()用于请求获取对象的锁,而Exit()用于释放对象的锁,最终达到线程同步的目的。 Monitor类的典型应用场景是在…

    多线程 2023年5月17日
    00
  • Apache ab并发负载压力测试实现方法

    一、Apache ab并发负载压力测试的背景 Apache ab是一个命令行工具,它可以用来进行HTTP/HTTPS等协议的并发负载压力测试。在进行网站或者应用程序的性能测试时,经常需要使用这个工具。 二、安装Apache ab 在大多数Linux操作系统上,Apache ab都已经包含在Apache web服务器软件包中。如果没有安装Apache软件包,可…

    多线程 2023年5月16日
    00
  • java多线程:基础详解

    Java多线程:基础详解攻略 什么是线程? 在计算机科学中,线程是指一个进程内部的单个执行流程。一个进程可以拥有多个线程,各个线程共享该进程的内存空间和系统资源,但每个线程拥有自己的程序计数器(PC)、栈和局部变量等。因此,多线程可以使程序在并发情况下更高效地运行。 如何创建线程? Java提供了两种方式来创建线程: 1.继承Thread类 在Java中,我…

    多线程 2023年5月17日
    00
  • Linux高并发踩过的坑及性能优化介绍

    Linux高并发踩过的坑及性能优化介绍 前言 首先需要明确的是,在开发高并发应用时,绝不仅仅是写出高并发的代码就够了,还需要在系统层面、网络层面和硬件层面做出一系列的优化,才能真正提高系统的性能和稳定性。 在本文中,我将从以下几个方面来讲解“Linux高并发踩过的坑及性能优化介绍”: 系统层面的优化 网络层面的优化 硬件层面的优化 系统层面的优化 1. 文件…

    多线程 2023年5月16日
    00
合作推广
合作推广
分享本页
返回顶部