文章来源:
参考内容:
前言:
在协作式线程调度器或者抢占式线程调度器上经常需要确保所有线程自身定期的暂停,这样其他的线程才可以有运行的机会.为了能让其他线程有机会运行,一个线程有10种方式可以暂停或者指示它准备暂停.主要分为下面几种方式:
(1)可以对I/O阻塞 (2)可以对同步对象阻塞 (3)可以放弃 (4)可以休眠 (5)可以连接另一个线程
(6)可以等待一个对象 (7)可以结束 (8)可以被更高级优先级线程抢占
(9)可以被挂起 (10)可以停止 (第9种和第10种已经被废弃掉,在这里不做介绍,具体废弃原因可以参照下面文章地址:
http://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html
要检查你编写的每一个run()方法,确保这些条件之一会以合理的频率出现.最后两种可能性已经废弃不用,因为他们会让对象处于不一致的状态,所以我们来看能够让线程称为虚拟机中协作的一员的其他8种方法.
一、阻塞
1 不论是对I/O阻塞还是对锁阻塞,都不会释放线程已经拥有的锁.
任何时候线程必须停下来等待它没有的资源时,就会发生阻塞.要让网络程序中的线程自动放弃CPU控制权,最常见的方式是对I/O阻塞.由于CPU比网络和磁盘快得多,网络程序经常会等待数据从网络到达或向网络发送数据时阻塞.即使只阻塞几毫秒,这一点时间也足够其他线程用来完成重要的任务.
线程在进入一个同步方法或代码块时也会阻塞.如果这个线程没有所同步对象的锁,而其他线程拥有这个锁,这个线程就会暂停,直到锁被释放为止.如果这个锁永远也不会释放,那么这个线程会永久停止.这种情况很常见,对于一个类中的某个方法,当存在多个线程执行当前类的同步方法时,上述描述的场景就会出现,比如说下面的发送请求的方法:
/**
* 发送请求
* @param events 请求事件集合
* @param compressed 是否压缩
* @return Lumberjack协议返回内容转换的响应对象
* @throws AdapterException
* @throws IOException
*/
private synchronized LumberjackResponse send(List<Event> events, boolean compressed) throws AdapterException, IOException {
int numberOfEvents = events.size();// 批量请求的数量
List<String> jsonList = new ArrayList<String>(numberOfEvents);