/Articles

线程分析-DeadLock

Java中谈线程问题必谈死锁,这种现象很奇怪。因为死锁的发生还是比较少见的,它是经典的线程问题但绝对不是常见的。它一般不会引起CPU使用过高,相反地,它会使得服务器停止对客户请求的响应。死锁的问题很容易就能从Thread Dump中识别出来。 这里有一点需要明确的是:死锁和CPU过高使用没有必然联系。但是网络上经常讲CPU过高和Java线程就归纳到死锁上来。这是不正确的。线程问题有很多种类,死锁只是其中一种很少见的情况。 下面通过具体的代码来演示死锁的产生,并通过Thread...

线程分析-CPU过高使用

Java线程问题中有一类现象很常见,就是CPU过高使用。有时你能看到400%的使用率,这是因为多核的原因,实际也就是100%或者99%而已。什么样的情况导致CPU过高,很难讲,情况太多,比如硬件资源、不好的算法、太过持久的IO吞吐等,都可能是成因。下面通过简单的例子,演示如何从Thread Dump中找到有问题的那个线程,直到有问题的代码行。 代码例子 这个代码只是演示而已,没人会这么写。 package zigzag.research.threaddump; public class HighCPU { public static void main(String[]...

使用Checksum对文件校验

企业应用中有时会使用到文档类文件的上传和下载。为了保证文档在传输和存储过程中没有被恶意篡改过,就可以使用Checksum对文件进行校验。比如在上传文件的同时,计算出文件的Checksum,保存到数据库中。当其他用户需要下载该文件时,对服务器上保存的该文件进行第二次的Checksum计算并和数据库中的值进行比较验证。 对于文件的checksum校验有非常多的方法,常见的有SHA1, MD5和CRC32。在Agile PLM中,文件的Checksum使用CRC32。对CRC算法感兴趣的可以查看此文:...

Java多线程 - 简单的线程池模式

在中间件等容器中,线程池是用的最多的管理线程与任务请求分配的方式。创建线程是需要消耗时间和内存的。在服务启动之初,就初始化一定数量的线程,其优点是保证这些数量的线程在内存设定的情况下一定会创建成功,并且节约了临时创建线程的时间。 线程池的工作原理大致为:为可以预期的大量请求创建一定数目的线程,当请求到来时,请求会被放入一个FIFO的列表中,线程池中的线程按照一定的优先调度获取这些请求,执行完后,再从请求列表中挨个获取下一个请求加以处理。在线程与请求处理过程中,会有两种情形出现: 一定数目的线程来不及处理大量的请求,请求会被挂起,直到线程有能力可以处理...

Java多线程 - 任务指派的临时线程

在我所提供技术支持的产品代码中,有一类模式非常普遍,就是主线程得到客户端的请求,在处理完必要的逻辑之后,再发送邮件通知或者JMS消息,而主线程在调用完这类消息通知发送后,完全不用等待消息通知的返回结果,马上返回。他们的实现方式大同小异,基本上都是将消息通知指派给一个临时新建的线程,而主线程即刻返回。使用这类任务指派给临时线程的模式,我总结了一下,有2个基本的条件: 这些任务不需要返回结果给主线程 必须是轻量的临时线程,没有复杂的线程调度,随即销毁,不占用全局线程池 基本上,使用简单的临时线程,通过匿名内部类就能实现。 // 处理前台逻辑 //...

Java多线程 - 中途放弃

如果有多个线程需要处理同一个资源,当一个线程已经处理完了,另外的线程根据资源的状态可以判断要不要也去处理。如果状态显示资源无须再处理,那么这些线程可以中途放弃。等到下次执行机会到来时再判断。这可能是一种比较节省资源的方式。和前面的保护性暂挂方式有一定的区别。保护性暂挂一直没有放弃,一直处于等待状态,当notify它时马上激活。而这里的中途放弃,则是测底放弃本次执行,等下一次机会的到来。...

Java多线程 - 保护性暂挂

有一种多线程工作环境,要求一件事情的开始起源于另外一件事情提供的资源的就绪。比如Java Message消息队列Queue。只有发送者Sender把消息实体组装完毕发送到queue中时,Reciever才能从queue中获取消息加以处理。也就是说Receiver的工作前提是消息队列中至少不为空。一旦消息队列为空的情况发生,Receiver必须挂起,暂停执行,以保证queue中有消息就绪。这种暂挂的目的是为了保护queue的资源可用。 下面的例子模拟这样的消息队列的输入输出。假设消息实体为: public class Message { String body;...

Java多线程 - 对象不可变模式

对象不可变模式,关注的是多线程的数据安全,是说参与多线程的对象一旦在第一个线程内建立,便不会再被第二个线程的外部方法所改变。假设通过Point和Line类做图形的画线程序。定义起始点p1和终点p2,通过Line构造函数来定义一个线段,并简单通过System.out.println(line)来表示画一条坐标为(1,100)-(2,200)的线段。 public class Main { public static void main(String args[]){ Point p1 = new Point(1, 100); Point p2 = new Point(2,...

Java多线程 - 单一执行模式

用synchronized实现单一执行模式 多个线程在共享同一个资源时,用synchronized方法给资源加上同步锁,确保在同一个时间点上,只有唯一的一个线程占用该资源,这是单一执行模式的概念。同步锁可以附加在方法体上,给类实例this加锁,比如: public synchronized void myMethod(){ // } 或者在方法体内,给共享资源对象加锁, public void myMethod(){ synchronized(obj){ // } }...

1 2 3