-
生产者消费者问题,长时间运行后线程waiting了5
有一个需求是对一个大数据量的数据集合进行处理。
目前采用的技术方案是使用生产者--消费者模式 + 多线程。
生产者负责从数据集合中获得数据;消费者负责对获取到的数据进行处理。
因为生产数据速度是相对较快的,而消费数据则相对较慢,为了达到较好的速度,在消费的那一侧采用了多线程消费。
使用了arrayblockqueue做为生产者和消费者的数据同步区。
大概代码是这样的:
//线程池 ExecutorService executorService = Executors.newFixedThreadPool(100); //生产 while(还有数据可以生产) { MyData data = product();//生产出一条数据 queue.put(data);//将这条数据加入到阻塞队列中 //调用多线程消费 executorService.execute(custom); }
//消费线程 public class Custom implements Runnable { public void run() { //从队列中取出数据 MyData data = queue.take(); //消费这个数据。。 } }
以上是代码的核心部分。
这样的程序在刚开始运行的还不错,速度和CPU占用率都达到了预订要求。
但是长时间运行之后,速度就降了下来。
用JDK的java visualVM查看,发现很多线程处于waiting状态。
等待的线程名称基本上是"pool-1-thread-xxxx"这样的。
于是我判断都是线程池里的线程。
因为采用了arrayblockarray,对列满了或者空了会自动阻塞。
现在估计是队列阻塞次数过多,导致了线程一直waiting.
不知这种情况,各位大大有什么建议没有?2012年6月15日 10:12
10个答案 按时间排序 按投票排序
-
其实对于多线程不需要使用arrayblockqueue的么 直接用ArrayQueue什么的,然后用synchronized关键字对put和get函数加锁,然后就能保证并发了么。。
2012年6月15日 11:23
-
引用
while(还有数据可以生产) { MyData data = product();//生产出一条数据 queue.put(data);//将这条数据加入到阻塞队列中 //调用多线程消费 executorService.execute(custom); }
感觉这样任务都积压在executorService.execute这句话上了,因为你定义了Executors.newFixedThreadPool(100),只能100个任务。当超过100个以后,任务都在排队,Custom.run就根本得不到执行,也即不会从队列里拿东西,那后来的任务因为队列满了,也放不进队列。所以就死啦。
我觉得不要ArrayBlockingQueue了,你都已经用线程池了,Executors.newFixedThreadPool(100),其实就是一个队列了。
或者用ArrayBlockingQueue,自己用一个线程或多个线程来take队列里的东西。2012年6月26日 15:32
-
//生产 while(还有数据可以生产) { MyData data = product();//生产出一条数据 queue.put(data);//将这条数据加入到阻塞队列中 //调用多线程消费 executorService.execute(custom); }
ArrayBlockingQueue是固定容量的,不知道你设了多少,我估计大于100,生产者不停在生产(调用executorService.execute(custom)),消费者来不及消费导致线程池阻塞现象严重。2012年6月16日 22:54
-
这个很好做。当生产者结束后,往队列里面塞一个结束标示,通知消费者也结束;我刚好写了一个这样的blog,你参考考:http://tangzhibin.iteye.com/blog/1561443
2012年6月15日 11:58
-
楼主的做法好像是生产者去告知消费者,消费者处于被动位置,导致消费者一直处于挤压状态。。如果100个消费进程都在运行,那就会导致消费线程处于等待状态,楼主可以考虑下 asyty 的思路
2012年6月15日 11:53
-
while(还有数据可以生产) { MyData data = product();//生产出一条数据 queue.put(data);//将这条数据加入到阻塞队列中 //调用多线程消费 executorService.execute(custom); }
你这里不是生产一个 才运行一次execute(custom)的嚒。。。我很好奇custom是同一个还是新new出来的额。。。于是一堆Custom就饥饿在那里了么。。。。
2012年6月15日 11:13
相关推荐
例如,寻找长时间处于WAITING或BLOCKED状态的线程,检查它们的堆栈跟踪以确定原因。 #### 11. `start()`方法执行原理 - **问题描述**:当我们调用`start()`方法时,发生了什么? - **执行过程**:调用线程的`start...
一种经典的并发模式,其中“生产者”线程负责生产数据,“消费者”线程负责消费数据。这种模型通常通过队列结构来实现。 - **死锁** 死锁发生在多个线程互相等待对方持有的锁而不释放的情况。防止死锁的方法包括...
- 是一种经典的线程协作模型,用来解决生产者和消费者之间的数据交换问题。 - 生产者负责生产数据,消费者负责消费数据,两者通过共享缓冲区进行通信。 #### 十、Java线程:并发协作-死锁 - **死锁**: - 发生...
通过观察线程执行的位置来判断是否有长时间运行的线程或疑似死循环的线程等。 #### 三、总结 以上总结了15个Java多线程面试题及其解答思路,涵盖了Java多线程的基本概念、实现技巧及常见问题。通过对这些问题的...
在Java中,多线程主要用于模拟现实世界中的并发行为,例如"生产者-消费者"模型。本文将深入探讨Java多线程的相关概念,帮助开发者理解和掌握这一技术。 1. **线程状态** Java线程有多种状态,包括新建(New)、...
- 生产者-消费者模型:利用BlockingQueue,线程之间通过队列进行数据交换。 - 线程池(ExecutorService):可以管理和控制线程数量,避免大量创建和销毁线程带来的性能开销。 5. **并发工具类**: - ...
- **问题**: 当生产者生成数据的速度与消费者处理数据的速度不匹配时,会出现问题。例如,如果生产者生成数据的速度过快,消费者处理不完,那么生产者就需要等待消费者处理完后再生成新的数据;反之亦然。 **2.2 ...
生产者消费者模型是多线程编程中常见的问题。可以通过以下方式实现: - 使用`synchronized`关键字保护共享资源。 - 生产者和消费者通过`wait()`和`notifyAll()`方法协调工作。 示例代码如下: ```java public ...
在本场景中,顾客被视为“生产者”,而理发师则被视为“消费者”。顾客的到来会导致一个计数器`count`增加,以指示理发师开始工作。第一位到达的顾客负责唤醒理发师,而其他顾客则会在有空闲座位时坐下等待,或者...
- **解析**: 生产者-消费者问题是一个经典的多线程问题,可以通过多种方式解决。一种常见的做法是使用阻塞队列作为两者之间共享的数据结构。生产者将数据放入队列,消费者从队列取出数据进行处理。还可以使用`...
另外,还有java.util.concurrent包下的BlockingQueue,它可以作为线程间的生产者-消费者模型,实现线程安全的数据交换。 此外,死锁、活锁和饥饿也是多线程编程中需要关注的问题。死锁是指两个或更多线程相互等待...
考虑运行三个生产者P1、P2和P3,以及一个消费者C1,所有进程从时间0开始可运行。 1. 如果使用时间片轮转调度执行这些进程,那么在10个时间单位后每个进程将生产了多少个产品,消费了多少个产品?假设初始运行队列的...
生产者-消费者模式是解决多线程同步问题的一种经典模型。生产者不断地产生消息放到队列中,而消费者不断地从队列中取出消息消费掉。这个过程需要确保队列不会溢出也不会为空。 - **BlockingQueue**:阻塞队列是一种...
6. **线程通信**:wait()、notify()和notifyAll()方法的使用,以及生产者消费者模型。 7. **线程状态**:理解NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING和TERMINATED六种线程状态。 8. **JVM内存模型**:了解...
- `BlockingQueue`:用于线程间数据传递,实现生产者消费者模式。 6. **线程池**: - `ExecutorService`和`ThreadPoolExecutor`:通过线程池管理线程,提高性能,避免频繁创建销毁线程的开销。 - `Executors`...
- 生产者和消费者之间通过条件变量或信号量进行同步。 #### 十二、基于TCP的网络通信的一般步骤 - **服务端步骤**: 1. 创建`ServerSocket`对象,并绑定到指定端口。 2. 调用`accept()`方法等待客户端连接。 3...
如果消费者的处理速度不足以跟上生产者的速度,就会导致阻塞。 在Java中,通常使用Jedis或Lettuce等库来操作Redis。当队列中的消息堆积,而消费者无法及时处理时,线程可能会进入阻塞状态。要检查线程的“stuck_...