new Thread(new Productor(queue)).start;
new Thread(new Customer(queue)).start;
}
}
class Customer implements Runnable {
private BlockingQueue<Integer> queue;
Customer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
@Override
public void run {
this.cusume;
}
private void cusume {
while (true) {
try {
int count = (int) queue.take;
System.out.println("customer正在消费第" + count + "个商品===");
// 只是为了方便观察输出结果
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace;
}
}
}
}
class Productor implements Runnable {
private BlockingQueue<Integer> queue;
private int count = 1;
Productor(BlockingQueue<Integer> queue) {
this.queue = queue;
}
@Override
public void run {
this.product;
}
private void product {
while (true) {
try {
queue.put(count);
System.out.println("生产者正在生产第" + count + "个商品");
count++;
} catch (InterruptedException e) {
e.printStackTrace;
}
}
}
}
//输出如下
/**
生产者正在生产第1个商品
生产者正在生产第2个商品
生产者正在生产第3个商品
生产者正在生产第4个商品
生产者正在生产第5个商品
customer正在消费第1个商品===
*/
2.2.3 LinkedBlockingQueue
基于链表的阻塞队列,内部也维护了一个数据缓冲队列 。需要我们注意的是如果构造一个LinkedBlockingQueue对象,而没有指定其容量大小 。
LinkedBlockingQueue会默认一个类似无限大小的容量(Integer.MAX_VALUE),这样的话,如果生产者的速度一旦大于消费者的速度,也许还没有等到队列满阻塞产生,系统内存就有可能已被消耗殆尽了 。
2.2.4 LinkedBlockingQueue和ArrayBlockingQueue的主要区别
- ArrayBlockingQueue的初始化必须传入队列大小,LinkedBlockingQueue则可以不传入 。
- ArrayBlockingQueue用一把锁控制并发,LinkedBlockingQueue俩把锁控制并发,锁的细粒度更细 。即前者生产者消费者进出都是一把锁 , 后者生产者生产进入是一把锁,消费者消费是另一把锁 。
- ArrayBlockingQueue采用数组的方式存?。?LinkedBlockingQueue用Node链表方式存取 。
Java提供了4种丢弃处理的方法,当然你也可以自己实现,主要是要实现接口:RejectedExecutionHandler中的方法 。
- AbortPolicy:不处理,直接抛出异常 。
- CallerRunsPolicy:只用调用者所在线程来运行任务,即提交任务的线程 。
- DiscardOldestPolicy:LRU策略,丢弃队列里最近最久不使用的一个任务,并执行当前任务 。
- DiscardPolicy:不处理,丢弃掉,不抛出异常 。
private static final int RUNNING = -1 << COUNT_BITS;
private static final int SHUTDOWN = 0 << COUNT_BITS;
private static final int STOP = 1 << COUNT_BITS;
private static final int TIDYING = 2 << COUNT_BITS;
private static final int TERMINATED = 3 << COUNT_BITS;
RUNNING:在这个状态的线程池能判断接受新提交的任务 , 并且也能处理阻塞队列中的任务 。
SHUTDOWN:处于关闭的状态,该线程池不能接受新提交的任务 , 但是可以处理阻塞队列中已经保存的任务 , 在线程处于RUNNING状态,调用shutdown方法能切换为该状态 。
STOP:线程池处于该状态时既不能接受新的任务也不能处理阻塞队列中的任务 , 并且能中断现在线程中的任务 。当线程处于RUNNING和SHUTDOWN状态,调用shutdownNow方法就可以使线程变为该状态 。
TIDYING:在SHUTDOWN状态下阻塞队列为空,且线程中的工作线程数量为0就会进入该状态,当在STOP状态下时 , 只要线程中的工作线程数量为0就会进入该状态 。
TERMINATED:在TIDYING状态下调用terminated方法就会进入该状态 。可以认为该状态是最终的终止状态 。
回到线程池创建ThreadPoolExecutor,我们了解了这些参数,再来看看ThreadPoolExecutor的内部工作原理:

文章插图
- 判断核心线程是否已满,是进入队列,否:创建线程
- 判断等待队列是否已满,是:查看线程池是否已满,否:进入等待队列
- 查看线程池是否已满,是:拒绝,否创建线程
进入Execute方法可以看到:
public void execute(Runnable command) {
if (command == )
throw new PointerException;
int c = ctl.get;
//判断当前活跃线程数是否小于corePoolSize,如果小于,则调用addWorker创建线程执行任务
推荐阅读
- iphone14技术规格
- 进程和线程:你了解它们的区别吗英语
- 阳光玫瑰葡萄大棚怎么建,阳光玫瑰葡萄种植技术与管理
- 荷兰豆种植 荷兰豆种植技术与管理
- 手机格式化照片用技术手段还会被恢复吗
- 蜜蜂怎么养殖 蜜蜂怎么养殖技术视频
- 物联网应用技术属于什么专业类别
- 现代式短跑技术强调的是什么跑法
- 蛋鸡养殖技术 蛋鸡养殖技术培训
- 物联网应用技术是什么
