## **目前有个任务是创建大量的数据同时向kafka里写入,于是之前开了大量的线程创建数据并写入,发现kafka并不能连接那么多线程,后来就用到生产者与消费者模式,大量的线程生产数据放入队列中,然后只开几个线程从队列中获取并写入kafka.**
**
**用到的技术:CountDownLatch,LinkedBlockingQueue,volatile,newFixedThreadPool**
1.线程池:
Java通过Executors提供四种线程池,分别为:
newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
我这里用到了newFixedThreadPool:
2.volatile
这里主要是标志生成是否结束,为了多线程的可见性,用到了volatile,主要是当主线程改变了flag,会及时的修改主存的值,并把线程中flag上效,然后线程会再从主存获取。
3.CountDownLatch
主要是计算线程是否多结束了
用到了
countDown() 结束一个线程就down一个
await();判断线程的数量是否为0,或则不会运行下的代码,一直在这路
4.LinkedBlockingQueue
是一个阻塞的线程安全的队列,底层采用链表实现
添加元素的方法有三个:add,put,offer,且这三个元素都是向队列尾部添加元素的意思。
区别:
add方法在添加元素的时候,若超出了度列的长度会直接抛出异常:
put方法,若向队尾添加元素的时候发现队列已经满了会发生阻塞一直等待空间,以加入元素。
offer方法在添加元素时,如果发现队列已满无法添加的话,会直接返回false。
从队列中取出并移除头元素的方法有:poll,remove,take。
poll: 若队列为空,返回null。
remove:若队列为空,抛出NoSuchElementException异常。
take:若队列为空,发生阻塞,等待有元素。
//主线程
try {
CDL=new CountDownLatch(createDateThreadNum);
PDL=new CountDownLatch(kafkaThreadNum);
//队列
LinkedBlockingQueue concurrentLinkedQueue = new LinkedBlockingQueue();
ExecutorService executorService =
Executors.newFixedThreadPool(createDateThreadNum+kafkaThreadNum);
for(int i=0;i
生产者线程
public void run() {
if(concurrentLinkedQueue!=null)
concurrentLinkedQueue.put(json);
if (CDL != null)
CDL.countDown();
}
消费者线程
public class ProducerRunnable implements Runnable {
private static Logger LOG = LoggerFactory.getLogger(ProducerRunnable.class);
private LinkedBlockingQueue concurrentLinkedQueue;
private static CountDownLatch PDL;
public static volatile boolean flag=true;
public ProducerRunnable(LinkedBlockingQueue concurrentLinkedQueue,Map settingMap,CountDownLatch PDL) {
this.concurrentLinkedQueue=concurrentLinkedQueue;
this.PDL=PDL;
}
public void run() {
if(concurrentLinkedQueue!=null)
{
//判断生产者是否结束与队列是否为空
//如果生产者结束并队列为空,则结束消费者线程
while (flag||!concurrentLinkedQueue.isEmpty()){
String json=concurrentLinkedQueue.take();
}
if(PDL!=null)
PDL.countDown();
}
}
}