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

yizhihongxing

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日

相关文章

  • Java线程的异常处理机制详情

    下面就是“Java线程的异常处理机制详情”的完整攻略。 异常处理机制概述 Java线程中的异常处理机制和单线程的异常处理机制是一致的,即异常抛出时会寻找异常处理函数(catch块、try-with-resources、或者未处理异常转交上一层调用栈),如果最终没有找到,则会导致线程终止。 在Java线程中,如果异常抛出没有被处理,或者异常处理函数中抛出了另一…

    多线程 2023年5月16日
    00
  • PHP解决高并发的优化方案实例

    PHP解决高并发的优化方案实例 近年来,随着互联网用户数量的飞速增长,高并发成为了许多网站开发者不得不面对的一个问题。对于使用PHP等后端语言的网站来说,如何针对高并发情况进行优化,将是一个非常重要的课题。以下是一些常见的PHP解决高并发问题的优化方案实例。 1. CDN加速 CDN(Content Delivery Network)即内容分发网络,是一种可…

    多线程 2023年5月16日
    00
  • web 性能测试中的几个关键指标(并发用户数,QPS,用户平均请求等待时间)

    在进行 Web 性能测试时,需要关注一些关键指标,以便评估网站的性能,提高用户体验和满意度。以下是几个重要的指标: 并发用户数 并发用户数指的是同时访问网站的用户数量。在进行并发测试时,需要模拟多个用户同时访问网站,以评估网站是否能够支持高并发。测试时需要逐步增加并发用户数,并记录每个用户请求的响应时间。通常,最大并发用户数是网站性能测试的一个重要指标。 示…

    多线程 2023年5月16日
    00
  • Java多线程编程中的并发安全问题及解决方法

    Java多线程编程中的并发安全问题及解决方法 1. 并发安全问题 Java多线程编程在实现高并发、高性能的同时,也带来了一些潜在的并发安全问题,如: 线程间数据竞争 线程间操作顺序问题 线程安全性问题 接下来,我们详细讲解这些问题。 1.1 线程间数据竞争 当多个线程同时对一个共享的变量进行读写时,会出现线程间数据竞争问题。因为操作系统的线程调度是不可控的,…

    多线程 2023年5月16日
    00
  • Java面试必备八股文整理

    首先我们先来了解一下什么是“八股文”。在面试中,某些问题或者某些知识点会被高频度地问到,这时就出现了某些标准的问法和答案,而这些标准的问法和答案就被称为“八股文”。接下来,我们就来详细讲解一下关于Java面试必备八股文整理的完整攻略。 什么是Java面试必备八股文整理 Java面试必备八股文整理,就是针对Java面试中最常被问到的一些问题和知识点进行整理,形…

    多线程 2023年5月17日
    00
  • springboot利用redis、Redisson处理并发问题的操作

    针对“Spring Boot利用Redis、Redisson处理并发问题”的操作攻略,我准备了如下内容。 1. 操作背景 在分布式应用程序中,如何解决并发请求所带来的资源竞争问题是一大难题。传统的互斥量等锁方法,效率较低,不适用于高并发场景,可以采用Redis和Redisson进行处理。Redis是一种基于内存的开源键值对存储系统,可以实现缓存和分布式锁。R…

    多线程 2023年5月17日
    00
  • Java并发编程深入理解之Synchronized的使用及底层原理详解 下

    Java并发编程深入理解之Synchronized的使用及底层原理详解 Synchronized简介 Synchronized是Java中最基本的互斥同步手段,它提供了一种独占的锁机制,同一时刻只能有一个线程访问被同步的代码块,其他线程必须等待当前线程释放锁后才能继续执行。 Synchronized的使用 Synchronized的使用非常简单,只需在方法或…

    多线程 2023年5月16日
    00
  • 新手了解java 多线程基础知识

    以下是“新手了解Java多线程基础知识”的完整攻略: 了解Java多线程 一、基础概念 在开始探讨Java多线程之前,需要了解一些基础概念: 1. 线程 线程是操作系统调度执行的最小单元,是进程中的一个执行流程,可以理解为程序执行的一条执行路径。 2. 多线程 允许在一个程序中同时运行多个线程,每个线程执行不同的任务,从而提高程序的性能。Java中可以使用T…

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