工作中,经常有将文件中的数据导入数据库的表中,或者将数据库表中的记录保存到文件中。为了提高程序的处理速度,可以设置读线程和写线程,这些线程通过消息队列进行数据交互。本例就是使用了LinkedBlockingQueue来模仿生产者线程和消费者线程进行数据生产和消费。
为了方便,这些不同的类被写在了一个类中,实际使用的时候,可以单独拆开,举一反三地使用。

以下是例子:

LinkedBlockingQueueDemo.java

import java.util.Date;
import java.util.Random;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit; public class LinkedBlockingQueueDemo {
// 生产者线程数量
private final static int providerThreadAmount = 5; // 记录每一个生产者线程是否处理完毕的标记
private static boolean[] providerDoneFlag = new boolean[providerThreadAmount]; // 整个所有的生产者线程全部结束的标记
private static boolean done = false; // 一个线程安全的队列,用于生产者和消费者异步地信息交互
private static LinkedBlockingQueue<String> linkedBlockingQeque = new LinkedBlockingQueue<String>(); static class ProviderThread extends Thread {
private Thread thread;
private String threadName;
private int threadNo; public ProviderThread(String threadName2, int threadNo) {
this.threadName = threadName2;
this.threadNo = threadNo;
} public void start() {
if (thread == null) {
thread = new Thread(this, threadName);
} thread.start();
System.out.println(
(new Date().getTime()) + " " + threadName + " starting... " + Thread.currentThread().getName());
} @Override
public void run() {
int rows = 0;
for (int i = 0; i < 100; i++) {
String string = String.format("%s-%d-%s", threadName, i, Thread.currentThread().getName());
// offer不会去阻塞线程,put会
//linkedBlockingQeque.offer(string);
linkedBlockingQeque.put(string);
rows++;
/*
* try { Thread.sleep((new Random()).nextInt(5) * 1000); } catch
* (InterruptedException e) { e.printStackTrace(); }
*/
} // 本线程处理完毕的标记
LinkedBlockingQueueDemo.providerDoneFlag[threadNo] = true;
System.out.println((new Date().getTime()) + " " + threadName + " end. total rows is " + rows + "\t"
+ Thread.currentThread().getName());
}
} static class ConsumerThread implements Runnable {
private Thread thread;
private String threadName; public ConsumerThread(String threadName2) {
this.threadName = threadName2;
} public void start() {
if (thread == null) {
thread = new Thread(this, threadName);
} thread.start();
System.out.println(
(new Date().getTime()) + " " + threadName + " starting... " + Thread.currentThread().getName());
} @Override
public void run() {
int rows = 0;
// 生产者线程没有结束,或者消息队列中有元素的时候,去队列中取数据
while (LinkedBlockingQueueDemo.getDone() == false || linkedBlockingQeque.isEmpty() == false) {
try {
//在甘肃电信的实际应用中发现,当数据的处理量达到千万级的时候,带参数的poll会将主机的几百个G的内存耗尽,jvm会提示申请内存失败,并将进程退出。网上说,这是这个方法的一个bug。
//String string = linkedBlockingQeque.poll(3, TimeUnit.SECONDS);
String string = linkedBlockingQeque.poll();
if (string == null) {
continue;
} rows++; System.out
.println((new Date().getTime()) + " " + threadName + " get msg from linkedBlockingQeque is "
+ string + "\t" + Thread.currentThread().getName());
/*
* try { Thread.sleep((new Random()).nextInt(5) * 1000); } catch
* (InterruptedException e) { e.printStackTrace(); }
*/ } catch (InterruptedException e) {
e.printStackTrace();
} }
System.out.println((new Date().getTime()) + " " + threadName + " end total rows is " + rows + "\t"
+ Thread.currentThread().getName());
}
} public static synchronized void setDone(boolean flag) {
LinkedBlockingQueueDemo.done = flag;
} public static synchronized boolean getDone() {
return LinkedBlockingQueueDemo.done;
} public static void main(String[] args) {
System.out.println((new Date().getTime()) + " " + "process begin at " + Thread.currentThread().getName());
System.out.println(
(new Date().getTime()) + " " + "linkedBlockingDeque.hashCode() is " + linkedBlockingQeque.hashCode()); // 启动若干生产者线程
for (int i = 0; i < providerThreadAmount; i++) {
String threadName = String.format("%s-%d", "ProviderThread", i);
ProviderThread providerThread = new ProviderThread(threadName, i);
providerThread.start();
} // 启动若干个消费者线程
for (int i = 0; i < 10; i++) {
String threadName = String.format("%s-%d", "ConsumerThread", i);
ConsumerThread consumerThread = new ConsumerThread(threadName);
consumerThread.start();
} // 循环检测生产者线程是否处理完毕
do {
for (boolean b : providerDoneFlag) {
if (b == false) {
/*
* try { Thread.sleep(3 * 1000); System.out.println((new Date().getTime()) +
* " "+"sleep 3 seconds. linkedBlockingQeque.size() is "+linkedBlockingQeque.
* size() + "\t" + Thread.currentThread().getName()); } catch
* (InterruptedException e) { e.printStackTrace(); }
*/ // 只要有一个生产者线程没有结束,则整个生产者线程检测认为没有结束
break;
} LinkedBlockingQueueDemo.setDone(true);
} // 生产者线程全部结束的时候,跳出检测
if (LinkedBlockingQueueDemo.getDone() == true) {
break;
}
} while (true); System.out.println((new Date().getTime()) + " process done successfully\t" + Thread.currentThread().getName());
}
}

结果略。

使用LinkedBlockingQueue来实现生产者消费者的例子的更多相关文章

  1. 通过生产者消费者模式例子讲解Java基类方法wait、notify、notifyAll

    wait(),notify()和notifyAll()都是Java基类java.lang.Object的方法. 通俗解释wait():在当前线程等待其它线程唤醒.notify(): 唤醒一个线程正在等 ...

  2. kafka集群配置和java编写生产者消费者操作例子

    kafka 安装 修改配置文件 java操作kafka kafka kafka的操作相对来说简单很多 安装 下载kafka http://kafka.apache.org/downloads tar ...

  3. Java设计模式—生产者消费者模式(阻塞队列实现)

    生产者消费者模式是并发.多线程编程中经典的设计模式,生产者和消费者通过分离的执行工作解耦,简化了开发模式,生产者和消费者可以以不同的速度生产和消费数据.这篇文章我们来看看什么是生产者消费者模式,这个问 ...

  4. java 多线程并发系列之 生产者消费者模式的两种实现

    在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度. 为什么要使用生产者和消费者模式 在线程世界里,生产者就是生产数据 ...

  5. 生产者-消费者问题:介绍POSIX线程的互斥量和条件变量的使用

    全局初始化互斥量和条件变量(不全局也行,但至少要对线程启动函数可见,这样才能使用.) static pthread_cont_t cond = PTHREAD_COND_INITIALIZER; st ...

  6. [Spark][kafka]kafka 生产者,消费者 互动例子

    [Spark][kafka]kafka 生产者,消费者 互动例子 # pwd/usr/local/kafka_2.11-0.10.0.1/bin 创建topic:# ./kafka-topics.sh ...

  7. LinkedBlockingQueue 实现 生产者 消费者

    转载:https://blog.csdn.net/sinat_36553913/article/details/79533606 Java中使用LinkedBlockingQueue实现生产者,消费者 ...

  8. go语言实现"生产者"和"消费者"的例子

    学习java的多线程的时候最经典的一个例子就是生产者消费者模型的例子,最近在研究go语言协程,发现go提供的sync包中有很多和java类似的锁工具,尝试着用锁工具配合协程实现一个"消费者& ...

  9. Java里的生产者-消费者模型(Producer and Consumer Pattern in Java)

    生产者-消费者模型是多线程问题里面的经典问题,也是面试的常见问题.有如下几个常见的实现方法: 1. wait()/notify() 2. lock & condition 3. Blockin ...

随机推荐

  1. elasticsearch系列(三)库表理解

    首先ES没有库和表的概念,只有index,type,document(详细术语可以看ES的系列一 http://www.cnblogs.com/ulysses-you/p/6736926.html), ...

  2. Gym - 100712H Bridges(边—双连通分量)

    https://vjudge.net/problem/Gym-100712H 题意: 给出一个图,求添加一条边后最少的桥数量. 思路: 参考了ZSQ大神的题解http://blog.csdn.net/ ...

  3. Dive into Spring framework -- 了解基本原理(二)--设计模式-part2

    Template模式 Template模式顾名思义是提供了一种模板,也就是针对某种业务提供了模范框架.这个在spring中是属于核心模式的,因为其ApplicationContext抽象类就是模板模式 ...

  4. 对dataframe中某一列进行计数

    本来是一项很简单的任务...但很容易忘记搞混..所以还是记录一下 方法一: df['col'].value_counts() 方法二: groups = df.groupby('col') group ...

  5. WPF TextBox 获得焦点后,文本框中的文字全选中

    textbox.GotFocus 事件处理 Textbox.SelectAll() 是不行的, 这样处理会发生的情况是: 1) textbox1 当前没有焦点, 内容为 someText. 2) 鼠标 ...

  6. h5 沉浸式状态栏

    1. manifest.json的plus节点里面配置 "plus": { "statusbar": {"immersed": true}, ...

  7. 三十 Python分布式爬虫打造搜索引擎Scrapy精讲—将selenium操作谷歌浏览器集成到scrapy中

    1.爬虫文件 dispatcher.connect()信号分发器,第一个参数信号触发函数,第二个参数是触发信号,signals.spider_closed是爬虫结束信号 # -*- coding: u ...

  8. 【转】ext4+delalloc造成单次写延迟增加的分析

    转自 http://blog.tao.ma/?p=58 这篇文章是淘宝内核组的刘峥同学在内部技术论坛上发表的一篇文章,但是由于刘峥同学目前没有blog,征得本人同意,贴在我的blog上,如果大家喜欢, ...

  9. 用Qt写了一个qq客户端,采用webqq协议,发出来和大家分享一下---大神请无视

    首先做以下声明: 本程序基于腾讯公司的webqq协议开发,所有相关版权归腾讯公司所有.此程序只用于技术交流和学习,不得用于其他方面. ---开发者:雨后星辰,转载请注明出处:http://www.cn ...

  10. 卸载Linux自带的JDK

    Redhat Enterprise Linux中自带了jdk的旧版本,往往需要卸载,卸载步骤如下: 在终端输入:yum remove java 终端显示:Is this ok[y/N]: 输入y,按回 ...