﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-casta-随笔分类-java</title><link>http://www.blogjava.net/casta/category/33082.html</link><description /><language>zh-cn</language><lastBuildDate>Mon, 10 Nov 2008 21:12:02 GMT</lastBuildDate><pubDate>Mon, 10 Nov 2008 21:12:02 GMT</pubDate><ttl>60</ttl><item><title>Java同步机制浅谈――synchronized对代码影响</title><link>http://www.blogjava.net/casta/archive/2008/11/10/239651.html</link><dc:creator>casta</dc:creator><author>casta</author><pubDate>Mon, 10 Nov 2008 05:54:00 GMT</pubDate><guid>http://www.blogjava.net/casta/archive/2008/11/10/239651.html</guid><wfw:comment>http://www.blogjava.net/casta/comments/239651.html</wfw:comment><comments>http://www.blogjava.net/casta/archive/2008/11/10/239651.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/casta/comments/commentRss/239651.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/casta/services/trackbacks/239651.html</trackback:ping><description><![CDATA[　　Java对多线程的支持与同步机制深受大家的喜爱，似乎看起来使用了synchronized关键字就可以轻松地解决多线程共享数据同步问题。到底如何？――还得对synchronized关键字的作用进行深入了解才可定论。<br />
总的说来，synchronized关键字可以作为函数的修饰符，也可作为函数内的语句，也就是平时说的同步方法和同步语句块。如果再细的分类， synchronized可作用于instance变量、object reference（对象引用）、static函数和class literals(类名称字面常量)身上。<br />
在进一步阐述之前，我们需要明确几点：<br />
A．无论synchronized关键字加在方法上还是对象上，它取得的锁都是对象，而不是把一段代码或函数当作锁――而且同步方法很可能还会被其他线程的对象访问。<br />
B．每个对象只有一个锁（lock）与之相关联。<br />
C．实现同步是要很大的系统开销作为代价的，甚至可能造成死锁，所以尽量避免无谓的同步控制。<br />
接着来讨论synchronized用到不同地方对代码产生的影响：<br />
假设P1、P2是同一个类的不同对象，这个类中定义了以下几种情况的同步块或同步方法，P1、P2就都可以调用它们。<br />
1． 把synchronized当作函数修饰符时，示例代码如下：<br />
Public synchronized void methodAAA()　{<br />
&nbsp; //&#8230;.<br />
}<br />
这也就是同步方法，那这时synchronized锁定的是哪个对象呢？它锁定的是调用这个同步方法对象。也就是说，当一个对象P1在不同的线程中执行这个同步方法时，它们之间会形成互斥，达到同步的效果。但是这个对象所属的Class所产生的另一对象P2却可以任意调用这个被加了 synchronized关键字的方法。<br />
上边的示例代码等同于如下代码：<br />
public void methodAAA() {<br />
&nbsp; synchronized (this) // (1)<br />
&nbsp; 　　{<br />
&nbsp;&nbsp; 　 //&#8230;..<br />
&nbsp; }<br />
}<br />
(1)处的this指的是什么呢？它指的就是调用这个方法的对象，如P1。可见同步方法实质是将synchronized作用于object reference。――那个拿到了P1对象锁的线程，才可以调用P1的同步方法，而对P2而言，P1这个锁与它毫不相干，程序也可能在这种情形下摆脱同步机制的控制，造成数据混乱：（<br />
2．同步块，示例代码如下：<br />
public void method3(SomeObject so) {<br />
&nbsp;&nbsp; synchronized(so)　{<br />
&nbsp;&nbsp;&nbsp;&nbsp; //&#8230;..<br />
&nbsp;&nbsp; }<br />
}<br />
这时，锁就是so这个对象，谁拿到这个锁谁就可以运行它所控制的那段代码。当有一个明确的对象作为锁时，就可以这样写程序，但当没有明确的对象作为锁，只是想让一段代码同步时，可以创建一个特殊的instance变量（它得是一个对象）来充当锁：<br />
class Foo implements Runnable　{<br />
private byte[] lock = new byte[0]; // 特殊的instance变量<br />
Public void methodA()　{<br />
&nbsp;&nbsp;&nbsp;&nbsp; synchronized(lock) { //&#8230; }<br />
&nbsp; }<br />
&nbsp; //&#8230;..<br />
}<br />
注：零长度的byte数组对象创建起来将比任何对象都经济――查看编译后的字节码：生成零长度的byte[]对象只需3条操作码，而Object lock = new Object()则需要7行操作码。<br />
3．将synchronized作用于static 函数，示例代码如下：<br />
Class Foo {<br />
&nbsp;&nbsp; public synchronized static void methodAAA() { // 同步的static 函数<br />
&nbsp;&nbsp; //&#8230;.<br />
&nbsp;&nbsp; }<br />
&nbsp;&nbsp; public void methodBBB() {<br />
&nbsp;&nbsp;&nbsp;&nbsp; synchronized(Foo.class) // class literal(类名称字面常量)<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
代码中的methodBBB()方法是把class literal作为锁的情况，它和同步的static函数产生的效果是一样的，取得的锁很特别，是当前调用这个方法的对象所属的类（Class，而不再是由这个Class产生的某个具体对象了）。<br />
记得在《Effective Java》一书中看到过将 Foo.class和 P1.getClass()用于作同步锁还不一样，不能用P1.getClass()来达到锁这个Class的目的。P1指的是由Foo类产生的对象。<br />
可以推断：如果一个类中定义了一个synchronized的static函数A，也定义了一个synchronized 的instance函数B，那么这个类的同一对象Obj在多线程中分别访问A和B两个方法时，不会构成同步，因为它们的锁都不一样。A方法的锁是Obj这个对象，而B的锁是Obj所属的那个Class。<br />
小结如下：<br />
搞清楚synchronized锁定的是哪个对象，就能帮助我们设计更安全的多线程程序。<br />
还有一些技巧可以让我们对共享资源的同步访问更加安全：<br />
1． 定义private 的instance变量+它的 get方法，而不要定义public/protected的instance变量。如果将变量定义为public，对象在外界可以绕过同步方法的控制而直接取得它，并改动它。这也是JavaBean的标准实现方式之一。<br />
2．如果instance变量是一个对象，如数组或ArrayList什么的，那上述方法仍然不安全，因为当外界对象通过get方法拿到这个instance 对象的引用后，又将其指向另一个对象，那么这个private变量也就变了，岂不是很危险。这个时候就需要将get方法也加上synchronized同步，并且，只返回这个private对象的clone()――这样，调用端得到的就是对象副本的引用了。<br />
<img src ="http://www.blogjava.net/casta/aggbug/239651.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/casta/" target="_blank">casta</a> 2008-11-10 13:54 <a href="http://www.blogjava.net/casta/archive/2008/11/10/239651.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java实现精确的四舍五入</title><link>http://www.blogjava.net/casta/archive/2008/11/10/239648.html</link><dc:creator>casta</dc:creator><author>casta</author><pubDate>Mon, 10 Nov 2008 05:34:00 GMT</pubDate><guid>http://www.blogjava.net/casta/archive/2008/11/10/239648.html</guid><wfw:comment>http://www.blogjava.net/casta/comments/239648.html</wfw:comment><comments>http://www.blogjava.net/casta/archive/2008/11/10/239648.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/casta/comments/commentRss/239648.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/casta/services/trackbacks/239648.html</trackback:ping><description><![CDATA[<br />
<strong>BigDecimal.ROUND_HALF_DOWN</strong> 如果最后一位&lt;=5则舍弃，如果&gt;5， 向前进一位。如7.5-&gt;7;7.6-&gt;8;-7.5-&gt;-7<br />
<br />
<strong>BigDecimal.ROUND_HALF_UP</strong> 如果最后一位&lt;5则舍弃，如果&gt;=5， 向前进一位。反之舍弃。如7.5-&gt;8;7.4-&gt;7;-7.5-&gt;-8<br />
<br />
<strong>BigDecimal.ROUND_UP</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 最后一位如果大于0，则向前进一位，正负数都如此。<br />
<br />
<strong>BigDecimal.ROUND_DOWN</strong> 最后一位不管是什么都会被舍弃。<br />
<br />
<strong>BigDecimal.ROUND_CEILING</strong> 如果是正数，按ROUND_UP处理，如果是负数，按照ROUND_DOWN处理。例如7.1-&gt;8; -7.1-&gt;-7;所以这种近似的结果都会&gt;=实际值。<br />
<br />
<strong>BigDecimal.ROUND_FLOOR</strong> 跟BigDecimal_ROUND_CEILING相反。例如7.1-&gt;7;-7.1-&gt;-8。这种处理的结果&lt;=实际值。<br />
<br />
<strong>BigDecimal.ROUND_HALF_EVEN</strong> 如果倒数第二位是奇数，按照BigDecimal.ROUND_HALF_UP处理，如果是偶数，按照 BigDecimal.ROUND_HALF_DOWN来处理。如7.5-&gt;8;8.5-&gt;8;7.4-&gt;7;-7.5-&gt;-8 <br />
<br />
<br />
<img src ="http://www.blogjava.net/casta/aggbug/239648.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/casta/" target="_blank">casta</a> 2008-11-10 13:34 <a href="http://www.blogjava.net/casta/archive/2008/11/10/239648.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>文件下载，文件名乱码的问题解决</title><link>http://www.blogjava.net/casta/archive/2008/07/18/215822.html</link><dc:creator>casta</dc:creator><author>casta</author><pubDate>Fri, 18 Jul 2008 07:33:00 GMT</pubDate><guid>http://www.blogjava.net/casta/archive/2008/07/18/215822.html</guid><wfw:comment>http://www.blogjava.net/casta/comments/215822.html</wfw:comment><comments>http://www.blogjava.net/casta/archive/2008/07/18/215822.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/casta/comments/commentRss/215822.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/casta/services/trackbacks/215822.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;只有注册用户登录后才能阅读该文。<a href='http://www.blogjava.net/casta/archive/2008/07/18/215822.html'>阅读全文</a><img src ="http://www.blogjava.net/casta/aggbug/215822.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/casta/" target="_blank">casta</a> 2008-07-18 15:33 <a href="http://www.blogjava.net/casta/archive/2008/07/18/215822.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>正则表达式</title><link>http://www.blogjava.net/casta/archive/2008/07/18/215696.html</link><dc:creator>casta</dc:creator><author>casta</author><pubDate>Fri, 18 Jul 2008 02:59:00 GMT</pubDate><guid>http://www.blogjava.net/casta/archive/2008/07/18/215696.html</guid><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;只有注册用户登录后才能阅读该文。<a href='http://www.blogjava.net/casta/archive/2008/07/18/215696.html'>阅读全文</a><img src ="http://www.blogjava.net/casta/aggbug/215696.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/casta/" target="_blank">casta</a> 2008-07-18 10:59 <a href="http://www.blogjava.net/casta/archive/2008/07/18/215696.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>