??xml version="1.0" encoding="utf-8" standalone="yes"?>另类图片亚洲校园小说区,亚洲国产精品国产自在在线,亚洲第一成年网站大全亚洲http://www.tkk7.com/yeshucheng/category/34002.htmlq逐自己,q逐方向,心随悟所?/description>zh-cnSun, 12 Dec 2010 13:43:20 GMTSun, 12 Dec 2010 13:43:20 GMT60Futurel合ExecutorService的简单实?/title><link>http://www.tkk7.com/yeshucheng/archive/2010/12/12/340393.html</link><dc:creator>叶澍?/dc:creator><author>叶澍?/author><pubDate>Sun, 12 Dec 2010 06:44:00 GMT</pubDate><guid>http://www.tkk7.com/yeshucheng/archive/2010/12/12/340393.html</guid><description><![CDATA[<p>//ValueObjectc?/p> <p> <div style="background-color: #eeeeee; font-size: 13px; border-left-color: #cccccc; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><span style="color: #0000FF; ">public</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">class</span><span style="color: #000000; "> AdEntity {<br />     </span><span style="color: #0000FF; ">private</span><span style="color: #000000; "> String id;<br />     </span><span style="color: #0000FF; ">private</span><span style="color: #000000; "> String name;<br />     </span><span style="color: #0000FF; ">private</span><span style="color: #000000; "> String broker;<br />     </span><span style="color: #0000FF; ">private</span><span style="color: #000000; "> String date;<br />     </span><span style="color: #0000FF; ">private</span><span style="color: #000000; "> String body;<br />     </span><span style="color: #008000; ">//</span><span style="color: #008000; ">get/set<img src="http://www.tkk7.com/Images/dot.gif" alt="" /></span><span style="color: #008000; "><br /> </span><span style="color: #000000; ">    <img src="http://www.tkk7.com/Images/dot.gif" alt="" /><br />     </span><span style="color: #0000FF; ">public</span><span style="color: #000000; "> String toString(){<br />         </span><span style="color: #0000FF; ">return</span><span style="color: #000000; "> </span><span style="color: #000000; ">"</span><span style="color: #000000; ">【编号ؓ:</span><span style="color: #000000; ">"</span><span style="color: #000000; ">+</span><span style="color: #000000; ">id</span><span style="color: #000000; ">+</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,q告名称?</span><span style="color: #000000; ">"</span><span style="color: #000000; ">+</span><span style="color: #000000; ">name</span><span style="color: #000000; ">+</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,代理商ؓ:</span><span style="color: #000000; ">"</span><span style="color: #000000; ">+</span><span style="color: #000000; ">broker</span><span style="color: #000000; ">+</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,发布日期?</span><span style="color: #000000; ">"</span><span style="color: #000000; ">+</span><span style="color: #000000; ">date</span><span style="color: #000000; ">+</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,内容?</span><span style="color: #000000; ">"</span><span style="color: #000000; ">+</span><span style="color: #000000; ">body</span><span style="color: #000000; ">+</span><span style="color: #000000; ">"</span><span style="color: #000000; ">?/span><span style="color: #000000; ">"</span><span style="color: #000000; ">;<br />     }<br /> }</span></div> </p> <p>//调用dc?/p> <p> <div style="background-color: #eeeeee; font-size: 13px; border-left-color: #cccccc; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><span style="color: #0000FF; ">public</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">class</span><span style="color: #000000; "> AdTask </span><span style="color: #0000FF; ">implements</span><span style="color: #000000; "> Callable</span><span style="color: #000000; "><</span><span style="color: #000000; ">AdEntity</span><span style="color: #000000; ">></span><span style="color: #000000; "> {<br />     @Override<br />     </span><span style="color: #0000FF; ">public</span><span style="color: #000000; "> AdEntity call() </span><span style="color: #0000FF; ">throws</span><span style="color: #000000; "> Exception {<br />         </span><span style="color: #008000; ">//</span><span style="color: #008000; "> 模拟q程调用p的一些时?/span><span style="color: #008000; "><br /> </span><span style="color: #000000; ">        Thread.sleep(</span><span style="color: #000000; ">5</span><span style="color: #000000; ">*</span><span style="color: #000000; ">1000</span><span style="color: #000000; ">);<br />         AdEntity vo</span><span style="color: #000000; ">=</span><span style="color: #0000FF; ">new</span><span style="color: #000000; "> AdEntity();<br />         vo.setId(String.valueOf(</span><span style="color: #0000FF; ">new</span><span style="color: #000000; "> Random().nextInt(</span><span style="color: #000000; ">1000</span><span style="color: #000000; ">)));<br />         vo.setName(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Ad@内衣q告</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />         vo.setBroker(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">CHANNEL</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />         Date date</span><span style="color: #000000; ">=</span><span style="color: #0000FF; ">new</span><span style="color: #000000; "> Date();<br />         SimpleDateFormat sdf</span><span style="color: #000000; ">=</span><span style="color: #0000FF; ">new</span><span style="color: #000000; "> SimpleDateFormat(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">yyyy-MM-dd</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />         String dateStr</span><span style="color: #000000; ">=</span><span style="color: #000000; ">sdf.format(date);<br />         vo.setDate(dateStr);<br />         vo.setBody(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">q端内容</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />         </span><span style="color: #0000FF; ">return</span><span style="color: #000000; "> vo;<br />     }<br /> }<br /> </span></div> </p> <p>//d?/p> <p> <div style="background-color: #eeeeee; font-size: 13px; border-left-color: #cccccc; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><span style="color: #0000FF; ">public</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">class</span><span style="color: #000000; "> TestQueryMemg {<br />     <br />     </span><span style="color: #008000; ">/**</span><span style="color: #008000; "><br />      * </span><span style="color: #808080; ">@param</span><span style="color: #008000; "> args<br />      * </span><span style="color: #808080; ">@throws</span><span style="color: #008000; "> ExecutionException <br />      * </span><span style="color: #808080; ">@throws</span><span style="color: #008000; "> InterruptedException <br />      </span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br />     </span><span style="color: #0000FF; ">public</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">static</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">void</span><span style="color: #000000; "> main(String[] args) </span><span style="color: #0000FF; ">throws</span><span style="color: #000000; "> InterruptedException, ExecutionException {<br />         ExecutorService exec</span><span style="color: #000000; ">=</span><span style="color: #000000; ">Executors.newCachedThreadPool();<br />         </span><span style="color: #008000; ">//</span><span style="color: #008000; ">创徏Future来完成网l调用Q?/span><span style="color: #008000; "><br /> </span><span style="color: #000000; ">        Callable</span><span style="color: #000000; "><</span><span style="color: #000000; ">AdEntity</span><span style="color: #000000; ">></span><span style="color: #000000; "> returnAd</span><span style="color: #000000; ">=</span><span style="color: #0000FF; ">new</span><span style="color: #000000; "> AdTask();<br />         Future</span><span style="color: #000000; "><</span><span style="color: #000000; ">AdEntity</span><span style="color: #000000; ">></span><span style="color: #000000; "> future</span><span style="color: #000000; ">=</span><span style="color: #000000; ">exec.submit(returnAd);<br />         <br />         </span><span style="color: #008000; ">//</span><span style="color: #008000; ">开始执行本地化查询信息</span><span style="color: #008000; "><br /> </span><span style="color: #000000; ">        AdEntity localAd</span><span style="color: #000000; ">=</span><span style="color: #0000FF; ">new</span><span style="color: #000000; "> AdEntity();<br />         localAd.setId(String.valueOf(</span><span style="color: #0000FF; ">new</span><span style="color: #000000; "> Random().nextInt(</span><span style="color: #000000; ">1000</span><span style="color: #000000; ">)));<br />         localAd.setName(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Ad@食品q告</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />         localAd.setBroker(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">蒙牛</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />         SimpleDateFormat sdf</span><span style="color: #000000; ">=</span><span style="color: #0000FF; ">new</span><span style="color: #000000; "> SimpleDateFormat(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">yyyy-MM-dd</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />         String dateStr</span><span style="color: #000000; ">=</span><span style="color: #000000; ">sdf.format(</span><span style="color: #0000FF; ">new</span><span style="color: #000000; "> Date());<br />         localAd.setDate(dateStr);<br />         localAd.setBody(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">内容本地</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br /> <br />         System.out.println(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">当前本地化查询内容ؓQ?/span><span style="color: #000000; ">"</span><span style="color: #000000; ">+</span><span style="color: #000000; ">localAd.toString());<br />         System.out.println(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">E等片刻以获取远端信?img src="http://www.tkk7.com/Images/dot.gif" alt="" /></span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />         <br />         </span><span style="color: #0000FF; ">while</span><span style="color: #000000; ">(</span><span style="color: #000000; ">!</span><span style="color: #000000; ">future.isDone()){<br />             </span><span style="color: #0000FF; ">try</span><span style="color: #000000; "> {<br />                 Thread.sleep(</span><span style="color: #000000; ">1</span><span style="color: #000000; ">*</span><span style="color: #000000; ">1000</span><span style="color: #000000; ">);<br />             } </span><span style="color: #0000FF; ">catch</span><span style="color: #000000; "> (InterruptedException e) {<br />                 e.printStackTrace();<br />             }<br />         }<br />         AdEntity entityRemote</span><span style="color: #000000; ">=</span><span style="color: #000000; ">(AdEntity)future.get();<br /> <br />         System.out.println(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">合ƈ查询内容为:\n</span><span style="color: #000000; ">"</span><span style="color: #000000; ">+</span><span style="color: #000000; ">localAd.toString()</span><span style="color: #000000; ">+</span><span style="color: #000000; ">"</span><span style="color: #000000; ">\n</span><span style="color: #000000; ">"</span><span style="color: #000000; ">+</span><span style="color: #000000; ">entityRemote.toString());<br />     }<br /> }</span></div> </p> <div><br /> </div> <p> </p> <p> </p> <p> </p> <img src ="http://www.tkk7.com/yeshucheng/aggbug/340393.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/yeshucheng/" target="_blank">叶澍?/a> 2010-12-12 14:44 <a href="http://www.tkk7.com/yeshucheng/archive/2010/12/12/340393.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多线E方法基理解http://www.tkk7.com/yeshucheng/archive/2009/07/20/287407.html叶澍?/dc:creator>叶澍?/author>Mon, 20 Jul 2009 02:00:00 GMThttp://www.tkk7.com/yeshucheng/archive/2009/07/20/287407.htmlhttp://www.tkk7.com/yeshucheng/comments/287407.htmlhttp://www.tkk7.com/yeshucheng/archive/2009/07/20/287407.html#Feedback0http://www.tkk7.com/yeshucheng/comments/commentRss/287407.htmlhttp://www.tkk7.com/yeshucheng/services/trackbacks/287407.htmlU程Q是指正在执行的一个指点o序列。在javaq_上是指从一个线E对象的start()开始。运?/span>runҎ体中的那一D늛对独立的q程?/span>

U程的ƈ发与q行

在过ȝ电脑都已?/span>CPU作ؓ主要的处理方式,无论?/span>PC或者是服务器都是如此。系l调用某一个时d能有一个线E运行。当然这当中采用了比较多的策略来做时间片轮询。通过不断的调度切换来q行U程q行Q而这U方式就叫做q发Q?/span>concurrentQ?/span>

随着工艺水^的逐渐提升Q?/span>CPU的技术也在不断增q。因此在如今多个CPU已经不是什么特别的Q而大家常总SMP的方式来形容多个CPU来处理两个或者两个以上的U程q行方式q为ƈ行(parallelQ?/span>

JAVAU程对象

                                          l承ThreadQ实?/span>start()Ҏ

要实现线E运行,JAVA中有两种方式Q?/span>

                                      实现RunnableQ然后再传递给Thread实例

注意Q线E对象和U程是两个截然不同的概念?/span>

U程对象?/span>JVM产生的一个普通的Object子类

U程?/span>CPU分配l这个对象的一个运行过E?/span>

public class Test {

 public static void main(String[] args) throws Exception{

    MyThread mt = new MyThread();

    mt.start();

    mt.join();

    Thread.sleep(3000);

    mt.start();

 }

}

当线E对?/span>mtq行完成?/span>,我们让主U程休息一下,然后我们再次在这个线E对象上启动U程.l果我们看到Q?/span>

Exception in thread "main" java.lang.IllegalThreadStateException

Ҏ原因是在以下源代码中扑ևQ?/span>

public synchronized void start() {

        if (started)
            throw new IllegalThreadStateException();

        started = true;

       group.add(this);

        start0();

 }

一?/span>Thread的实例一旦调?/span>start()ҎQ这个实例的started标记标CؓtrueQ事实中不管q个U程后来有没有执行到底,只要调用了一?/span>start()再也没有机会运行了Q这意味着Q?/span>

【通过Thread实例?/span>start()Q一?/span>Thread的实例只能生一个线E?/span>

interrupt()Ҏ

当一个线E对象调?/span>interrupt()ҎQ它对应的线Eƈ没有被中断,只是改变了它的中断状态。当前U程的状态变以中断状态,如果没有其它影响Q线E还会自ql执行。只有当U程执行?/span>sleepQ?/span>waitQ?/span>join{方法时Q或者自己检查中断状态而抛出异常的情况下,U程才会抛出异常?/span>

join()Ҏ

join()ҎQ正如第一节所aQ在一个线E对象上调用joinҎQ是当前U程{待q个U程对象对应的线E结?/span>

例如Q有两个工作Q工?/span>A要耗时10U钟Q工?/span>B要耗时10U或更多。我们在E序中先生成一个线E去做工?/span>BQ然后做工作A?/span>

        new B().start();//做工?/span>B

A();//做工?/span>A

工作A完成后,下面要等待工?/span>B的结果来q行处理。如果工?/span>Bq没有完成我׃能进行下面的工作CQ所以:

B b = new B();

b.start();//做工?/span>B

A();//做工?/span>A

b.join();//{工?/span>B完成.

C();//l箋工作C

原则Q?/span>join是测试其它工作状态的唯一正确Ҏ?/span>

yield()Ҏ

yield()Ҏ也是cL法,只在当前U程上调用,理由同上Q它L让当前线E放弃本ơ分配到的时间片Q调用这个方法不会提高Q何效率,只是降低?/span>CPU的d期上面介l的U程一些方法,Z(基础?/span>)而言只能单提及。以后具体应用中我会l合实例详细?/span>

原则Q【不是非常必要的情况下,没有理由调用它?/span>

wait()?/span>notify()/notityAll()Ҏ

首先明确一点他们的属于普通对象方法,q是线E对象方法;其次它们只能在同步方法中调用。线E要惌用一个对象的wait()Ҏp先获得该对象的监视锁,而一旦调?/span>wait()后又立即释放该锁?/span>

U程的互斥控?/span>

多个U程同时操作某一对象Ӟ一个线E对该对象的操作可能会改变其状态,而该状态会影响另一U程对该对象的真正结果?/span>

synchornized关键?/span>

把一个单元声明ؓsynchornized,可以让在同一旉只有一个线E操作该Ҏ。作忆可以把synchronized看作是一个锁。但是我们要理解锁是被动的,q是d的呢Q换而言之它到底锁什么了Q锁谁了Q?/span>

例如Q?/span>

synchronized(obj){

                 //todo…

}

如果代码q行到此处,synchronized首先获取obj参数对象的锁Q若没有获取U程只能{待Q如果多个线E运行到q只能有一个线E获?/span>obj的锁Q然后再执行{}中的代码。因?/span>obj作用范围不同Q控制程序也不同?/span>

如果一个方法声明ؓsynchornized的,则等同于把在ZҎ上调?/span>synchornized(this)?/span>

如果一个静态方法被声明?/span>synchornizedQ则{同于把在ؓ个方法上调用synchornized(c?/span>.class)

 

真正的停止线E?/span>

要让一个线E得到真正意义的停止Q需要了解当前的U程在干什么,如果U程当前没有做什么,那立刻让Ҏ退出,当然是没有Q何问题,但是如果Ҏ正在手头赶工Q那必让他停止,然后收拾D局。因此,首先需要了解步骤:

1.     正常q行Q?/span>

2.       处理l束前的工作,也就是准备结束;

3.       l束退出?/span>

注:以上部分概括某位牛h大哥的笔讎ͼl常拜读他的博客

]]>
认识~冲区Bufferhttp://www.tkk7.com/yeshucheng/archive/2009/02/13/254603.html叶澍?/dc:creator>叶澍?/author>Fri, 13 Feb 2009 12:56:00 GMThttp://www.tkk7.com/yeshucheng/archive/2009/02/13/254603.htmlhttp://www.tkk7.com/yeshucheng/comments/254603.htmlhttp://www.tkk7.com/yeshucheng/archive/2009/02/13/254603.html#Feedback0http://www.tkk7.com/yeshucheng/comments/commentRss/254603.htmlhttp://www.tkk7.com/yeshucheng/services/trackbacks/254603.html数据对于输入和输出的操作耗时是非怸重的问题Q如果把q个问题攑օ到网l上ȝ待更甚是值得注意的一个问题了。假如结合基?/span>OS知识我们也知道如果要减少q种I/O操作的耗时或者也可以说提升这U效率的话,最大的可能是减少物理d的次敎ͼ而且可能做C存数据的重读性(操作pȝ也在加强说明更多减少抖动现象的生)?/span>

?/span>java.nio包中我们可以直接来操作相对应?/span>API了。可以让java更加方便的直接控制和q用~冲区。缓冲区有几个需要了解的特定概念需要详来解释Q才能更好的知道我们下面一些列需要针对的问题实质?/span>

属?/span>

定wQ?/span>capacityQ:֐思义是表示~冲Z可以保存多少数据Q?/span>

极限Q?/span>limitQ:~冲Z的当前数据终l点。不q它是可以动态改变的Q这样做的好处也是充分利用重用性;

位置(position)Q这个也好理解,其实是指明下一个需要读写数据的位置?/span>

上面上个关系q可以具体用囄的方式来表达整体概念Q如下图所C:


在极限的时候就说到可以修改它,所以对于它的操作由以下ҎQ?/span>

l         clear()Q首先把极限讄为容量,再者就是需要把位置讄?/span>0Q?/span>

l         flip()Q把极限讄Z|区Q再者就是需要把位置讄?/span>0Q?/span>

l         rewind()Q不改变极限Q不q还是需要把位置讄?/span>0?/span>

最为最基础的缓冲区ByteBufferQ它存放的数据单元是字节。首先要的是ByteBuffer没有提供公开的构造方法,只是提供了两个静态的工厂Ҏ?/span>

l         allocate(int capacity)Q返回一?/span>ByteBuffer对象Q参数表C缓冲区定w大小?/span>

l         allocateDirect (int capacity)Q返回一?/span>ByteBuffer对象Q参C是一栯C缓冲区定w大小?/span>

在这里需要注意的是在使用两者的时候需要特别小心,allocateDirect和当前操作系l联pȝ非常紧密Q它牉|C?/span>native method的方法,大家知道一旦本地方法就是需要考虑调用dllQ动态链接库Q这个时候基本也失MJAVA语言的特性,a外之意对于耗资源非常大。所以如果考虑到当前用的~存区比较庞大而且是一个长期驻留用的Q这个时候可以考虑使用它?/span>



]]>
从套接字衍生到RMI代码思\http://www.tkk7.com/yeshucheng/archive/2009/02/03/253144.html叶澍?/dc:creator>叶澍?/author>Tue, 03 Feb 2009 13:56:00 GMThttp://www.tkk7.com/yeshucheng/archive/2009/02/03/253144.htmlhttp://www.tkk7.com/yeshucheng/comments/253144.htmlhttp://www.tkk7.com/yeshucheng/archive/2009/02/03/253144.html#Feedback3http://www.tkk7.com/yeshucheng/comments/commentRss/253144.htmlhttp://www.tkk7.com/yeshucheng/services/trackbacks/253144.html阅读全文

]]>
RMI的原理和实现http://www.tkk7.com/yeshucheng/archive/2009/02/02/252932.html叶澍?/dc:creator>叶澍?/author>Mon, 02 Feb 2009 04:04:00 GMThttp://www.tkk7.com/yeshucheng/archive/2009/02/02/252932.htmlhttp://www.tkk7.com/yeshucheng/comments/252932.htmlhttp://www.tkk7.com/yeshucheng/archive/2009/02/02/252932.html#Feedback3http://www.tkk7.com/yeshucheng/comments/commentRss/252932.htmlhttp://www.tkk7.com/yeshucheng/services/trackbacks/252932.html 

 

lD

       Rmi自从JDK1.1已l出C。而对于ؓ什么在JAVA的世界里需要一个这?/span> 思想理念需要看下:RMI问世由来。其实真正在国内使用到它的比较少Q不q在前些q比较火?/span>EJB是在它的基上进一步深化的。从本质上来?/span>RMI的兴h是ؓ了设计分布式的客戗服务器l构需求而应q而生的,而它的这U?/span>B/Sl构思想能否和我们通常?/span>JAVA~程更加贴切呢?a外之意就是能否让q种分布式的状态做到更加透明Q作为开发h员只需要按照往怸样开?/span>JAVA应用E序一h开发分布式的结构。那现在的问题是如何来划q个`沟呢Q首先我们来分析下在JAVA世界里它的一些特点因素:

l         JAVA使用垃圾攉定对象的生命周期?/span>

l         JAVA使用异常处理来报告运行期间的错误。这里就要和我们|络通讯中的异常相联pv来了。在B/Sl构的网l体pM我们的这U错误性是非常常见的?/span>

l         JAVA~写的对象通过调用Ҏ来调用。由于网l通讯把我们的客户与服务器之间阻隔开了。但是代理的一U方式可以很好的提供一U这L假象Q让开发h员或者用者都感觉是在本地调用?/span>

l         JAVA允许一U高U的使用cd载器Q?/span>CLassLoaderQ机制提供系l类路径中没有的cR这话什么意思?

主要特点

上面说到了分布式的方式和我们?/span>JAVA中如何更好的划^q个鸿沟Q需要具备的特质?/span>

那这里我们来看看我们所谓的RMI到底跟我们普通的JAVAQ或者说JavaBeanQ存在一些什么样的差异:

l         RMIq程异常Q?/span>Remote ExceptionQ:在上面我们也提到了一个网l通讯隑օ有一些无论是软gU别的还是硬件别的异常现象Q有时候这些异常或许是一U无法预知的l果。让我们开发h~如何来回溯q种异常信息Q这个是我们开发h员要兛_的。因此在调用q程对象的方法中我们必须在远E接口中Q接口是一U规范的标准行ؓQ所以在调用的这个方法体上需要签名注明:java.rmi,RemoteException.。这也就注明了此Ҏ是需要调用远E对象的?/span>

l         g?/span> Q当把对象作为参C递给一个普通的JAVA对象Ҏ调用Ӟ只是传递该对象?strong>引用。请注意q里谈到的是对象?#8220;引用”一词,如果在修改该参数的时候,是直接修改原始对象。它q不是所谓的一个对象的备䆾或者说拯Q说白了是在本JVM内存中的对象Q。但是如果说使用的是RMI对象Q则完全是拷贝的。这与普通对象有着鲜明的对比。也正是׃q种拯的资源消耗造就了下面要说到的性能~失了?/span>

l         调用开销Q凡是经q网l通讯理论上来说都是一U资源的消耗。它需要通过~组与反~组方式不断解析cd象。而且RMI本n也是一U需要返回值的一个过E定义?/span>

l         安全?/span>Q一谈到|络通讯势必会说到如何保证安全的q行?/span>

 

概念定义

在开始进行原理梳理之前我们需要定义清楚几个名词。对于这些名词的理解影响到后的深入进行?/span>

1.         StubQ存根,有些书上也翻译成Q桩基在EJB的相关书c中ؓ体现q个意思)Q?/span>

q里举例说明q个概念P或许不够恰当Q。例如大家因公出差后Q都有存在一些报销的发或者说票。对于你当前手头所拿到的发ƈ不是一个唯一的,它同时还在你发生消费的地Ҏ一个复CgQ而这个复Cg是所谓的存根。但是这个存根上q没有很多明l的描述Q只是有一个大概的金额定义。它把很多的l节费用都忽略了。所以这个也是我们说的存根定义。而在我们RMI的存根定义就是用了q样一个理解:在与q程发生通讯调用Ӟ把通讯调用的所有细节都通过对象的封装Ş式给隐藏在后端。这本nq?/span>OOAD的意思理c而暴露出来的是我们的接口方式,而这U接口方式又和服务器的对象具有相同的接口Q这里就和我们前面D例说的报销单据联系上了Q报销单据的存根不知道会有一个什么Ş式发生具体问题,而你手执的发具体就需要到贵公司去报销费用Q而这里的公司财务处就是所谓的服务器端Q它才是真正q实质性问题的。)因此作ؓ开发h员只需要把_֊集中在业务问题的解决上,而不需要考虑复杂的分布式计算。所有这些问题都交给RMIM一处理?/span>

2.         Skeleton(一些书译叫骨Ӟ也叫l构?/span>)Q它的内部就是真正封装了一个类的Ş成调用体现机制。包括我们熟知的ServerSocket创徏、接受、监听、处理等?/span>

3.         Mashalling(~组)Q在内存中的对象转换成字节流Q以便能够通过|络q接传输?/span>

4.         Unmashalling(反编l?/span>)Q在内存中把字节{换成对象Q以便本地化调用?/span>

5.         Serialization(序列?/span>)Q编l中使用到的技术叫序列化?/span>

6.         Deserializationg(反序列化)Q反~组中用到的技术叫反序列化?/span>

 

客户?/span>

       既然我们知道stub主要是以接口的方式来暴露体现Q?/span>stub主要 也是以代理的方式来具体实施。那?/span>RMI中的q种接口有哪些特性呢Q(Remote InterfaceQ?/span>

1)        必须扩展Q?/span>extendsQ?/span>java.rmi.Remote接口Q因E接口ƈ不包含Q何一个方法,而是作ؓ一个标记出?/span>Q它是需要告?/span>JVM?/span>RunTime的时候哪些是常规对象Q哪些属于远E对象。通过q种标识的定义能?/span>JVM了解cM哪些Ҏ需要编l,通过了编l的方式才能通过|络序列化的调用Q?/span>

2)        接口必须?/span>publicQ公共)Q它的好处不a而喻的——能够方便的让所有h员来调用?/span>

3)        接口Ҏq需要以异常抛出Q例如:RemoteExceptionQ,至于它的用处我们在前面也提到q里׃再复qͼ

4)        在调用一个远E对象期_q行期间Q,Ҏ的参数和q回值都要必L可序列化的。至于ؓ什么需要这么做Q这里的~由不用多说大家也应该清楚了解?/span>

服务?/span>

       既然我们知道stub所做的事情是一个简单的代理转发动作Q那我们真正要做的对象就在服务端来做了。对于用简单的RMI我们直接L定,但是往往一旦用了RMI对象存在非常多的远E方法调用,q个时候服务器端对于这么多的调用如何来判别或者说识别呢?q里p说到的是对于RMI实现它会创徏一个标识符Q以便以后的stub可以调用转发l服务器对象使用了,而这U方式我们通常叫服务器RMI的注册机制。言外之意就是让服务器端的对象注册在RMI机制中,然后可以导出让今后的stub按需来调用。那它又是如何做到这U方式的呢?对于RMI来说有两U方式可以达到这U效果:

a)         直接使用UnicastRemoteObject的静态方法:exportObjectQ?/span>

b)        l承UnicastRemoteObjectcd~省的构造函?/span>exportObject?/span>

现在大家又会问他们之间又有什么区别呢Q我该用哪U方式来做呢Q这不是很难做抉择吗Q从一般应用场景来说区别ƈ不是很大Q但是,q里说了“但是”哦,呵呵。大家知道承的方式是把父类所具备的所有特质都可以完好无损的承到子类中而对于类的总老大Q?/span>Object来说里面有:equals()?/span>hashCode()?/span>toString(){方法。这是个什么概念呢Q意思就是说如果对于本地化的调用Q他们两个的ҎQ?/span>a,bQ基本区别不是很大。但是我们这里强调的RMI如果是一U分布式的特定场景,具备使用哈希表这U特性就昑־ؓ重要了?/span>

刚才说了服务端采用什么方法行为导出对象的。那现在导出后的对象又对应会发生什么情况呢Q?/span>

首先被导出的对象被分配一个标识符Q这个标识符被保存ؓQ?/span>java.rmi.server.ObjID对象中ƈ被放C个对象列表中或者一个映中。而这里的ID是一个关键字Q而远E对象则是它的一个|说到q大家有没有觉得它原理非常像HashMap的特质呢Q没错,其实是使用了它的特性)Q这样它可以很好的和前面创建的stub沟通。如果调用了静态方?/span>UnicastRemoteObject.export(Remote …)Q?/span>RMI׃选择L一个端口号Q但q只是第一调用发生在随后的exportObject每次调用都把q程对象导出到该q程对象W一被导出时使用的端口号。这样就不会产生混ؕQ会把先前一一导出的对象全部放入到列表中。当然如果采用的是指定端口的Q则按照对应昄的调用方式用。这里稍作强调的是一个端口可以导ZQ意数目的对象?/span>

Q待l?/span>……Q?/span>

]]>
RMI问世由来http://www.tkk7.com/yeshucheng/archive/2009/02/02/252931.html叶澍?/dc:creator>叶澍?/author>Mon, 02 Feb 2009 03:57:00 GMThttp://www.tkk7.com/yeshucheng/archive/2009/02/02/252931.htmlhttp://www.tkk7.com/yeshucheng/comments/252931.htmlhttp://www.tkk7.com/yeshucheng/archive/2009/02/02/252931.html#Feedback1http://www.tkk7.com/yeshucheng/comments/commentRss/252931.htmlhttp://www.tkk7.com/yeshucheng/services/trackbacks/252931.html    大家都知道对于互联网的世界网l通讯是其本质特征。而对于一个分布式式计来说更是如此。在它的环境中用了客户/服务器结构特点,使用的一个核心技术就是网l通讯层。在最早的OSI的概念基上,建立了完善具体协议层。而客h要能够与位于其他物理层主Z的服务器通讯Q需要能够想服务器发送数据,然后以某U方式获得响应。这当中q涉到我们熟悉的协议层面了Q在q里׃再复q这些协议概念了。对于网l通讯来说我们所要了解的是最为常用的是两种q接方式Q无q接协议Q?/span>UDPQ、面向连接协议(TCP/IPQ?/span>

       多数|络~程库中Q以JAVAZ来说明)Q在JAVAq_中一L提供了这些元素。而作为面向连接协议来说用的是套接字Q?/span>SocketQ进行了更进一步的抽象描述。一般我们在JAVA的网l编E中都觉得在使用套接字这块相Ҏ便,它不需要你L多的了解操作pȝ的细节以及硬件的传递处理方式?/span>TCP/IP的所有细节之处都得到了套接字的封装用,让程序员xC务层面的处理?/span>

       对象是一U抽象思维物质Q对于计机来说它只Ҏ字电路的存储方式能够加以识别而且在网l传输当中也是一U信号量Q而这一切只有用字节流方式传输才是真正需要做到的。所以在本地L与远E服务器的通讯传输在对象与字节流之间不断怺转化才是我们真正需要的人性物质与机器所需要的。(有点墨迹了,切入整体QM来说是需要两U方式来认定q种传输行ؓQ编l(MarshallingQ与反编l(UnmarshallingQ。而这一切的手段方式才是通过Q序列化Q?/span>SerialiazableQ与反序列化的方式不断完成。如下图所C:

 

图:对象到字节再到对象的转换

       对于数据的传输本质就是上图说明的。那我们一般是如何使用套接字来构造我们这一行ؓ呢?对于q里的主要是一U大致方法说明,所以只能以部分代码来说明客L怎么来发送这个请求?/span>

Socket socket=new Socket("http://www.wgh.com.cn",8888);

    OutputStream out=socket.getOutputStream();

    ObjectOutputStream obj=new ObjectOutputStream(out);

    obj.writeObject(object);

    InputStream in=socket.getInputStream();

    ObjectInputStream objIn=new ObjectInputStream(in);

    Object objFoo=(Object)objIn.readObject();

    //todo q里是具体q行操作的相关传值参数处理了

    obj.close();

    objIn.close();

    socket.close();

而作为服务器的接收方则把以上数据做一个逆{相反处理可以。即服务器需要读取发送过来的对象数据Q最l得到结果。现在假设还是一个甚x多这L对象处理Q我们又要处理和以上代码差不多的q程。好Q到q里我们可曾惛_N没有一U办法把q些q多的重复过E做一个通用的方式来提供吗?我如果不惛_做这些繁杂的对象处理可以吗?比如Q我想直接得刎ͼ

//其中clientObjectji是从客L传输q来的副本;

MyObject myObject=server.getFoo(clientObject);

q样p让我们把底层的那些庞杂数据{换能够透明装h呢?既然q个问题一l提出,那就意味着肯定有很多类似的需求。技术永q都是在需求的提出应运而生的。上面提出的需求就是我们要讨论的,既然我们x一些套接字的重复处理过E来个封装清理,那需要面对的问题是什么呢Q?/span>

1.      能够把所有的相同处理q程全部都移入到服务端呢Q?/span>

2.      对于客户端来说能否只预留接口行ؓ呢?

3.      把过多的复杂处理q程完善的做个封装?

4.      如果以上q程能够形成Q那客户端又是如何办到可以连接到服务器端的组件行为呢Q?/span>

既然能够把遇到的问题提出然后ȝ出来也就意味着我们需要去解决它。不知道是否q?/span>

记得设计模式中有一个叫Q代理模式?没错Q就是这个代理模式开始我们的描述。代理是一个实现给定接口的对象Q但是不直接L行代码结果,而是代表其他一些对象执行实际计的对象。怎么理解q个话呢QD例说Q如今很多城市都有火车票或者飞机票的代售点Q这里的代售点其实就是采用了一U代理机制。我们想买某天的火R或者飞机票有时候ƈ不需要到火R站或者飞机票的ȝ去购买票Q而是找一个你最q的代售点去购买。代售点是起到一个中间桥梁的作用Q至于买h员无需兛_他们如何去订购,q些具体的动作都׃们内部去处理Q你只关心最l是否有你需要的就行。知道这个原理接下来好理解很多了,我们最好以cd的方式来说明q个代理的机Ӟ如图所C:


 

    到这里如果还觉得抽象Q没关系接下来我以更加脓切的实例来结合类囄方式l出对应的参照说明。假如我们把上面?/span>proxy模式再做个深入的探讨剖析Q结合上面说的客L发送参C求和提出的问题综qͼ。大安知道一个接口是能够在安全甚臛_扩展上能够帮助我们非常大的功能。作为客L最为希望的是只关心我们需要的参数Q或者变量)、返回|而它如何而来Q做了哪些具体工作这些都不是客户端关心的?/span>Ok,现在l合我们说的接口方式Q确实可以解册个问题(接口的简单化Q没有具体实玎ͼQ但是你可能会问Q?/span>

1.      既然接口如此单,那参数又是如何传递过ȝ呢?

2.      服务端又如何知道我要的是什么呢Q?/span>

带着问题我们来解册个问题,当然也是大家所兛_的问题了。现在开始要对于上面?/span>proxy模式做个深入剖析了。我们先来看一?/span>proxy模式演变的过E的囄Q?

 

图:RMI核心l构

    我们可以从图C看Z传统?/span>proxy模式变化C个变化的l构有什么不同呢Q对于先前我们提出的两个问题可以很好的做出解释了:

n         既然接口如此单,那参数又是如何传递过ȝ呢?

A:既然是对客户端只开接口暴露Q那么我们是需要一个后台的socket来传输接口中已经定义好的参数Q通过参数的编l(序列化)方式h到远E服务上d应处理。这当中要求定义到对Ҏ务的服务名称和端口号。(q里也就是我们最先提到的那段代码了)

n         服务端又如何知道我要的是什么呢Q?/span>

A:ok,既然客户端是通过socket来发送数据,那势必一定需?/span>ServerSocket来做q个响应的接收处理了。问题是传过来的参数如何与我们的业务实现cd联上呢?所以这个也是skeleton的职责所在了Q在skeleton的封装处理中Q启动中把响应实现cȝ嵌入Q聚合实现类Q,然后通过c{换处理和匚w处理来得到需要响应的l果了?/span>

   

    本来说到q想大概有个收尾Q但是总觉得还没有把一些问题说透彻。烦性想再深入写写?br />     从套接字衍生到RMI代码思\



]]>
HashMap原理及冲H之?/title><link>http://www.tkk7.com/yeshucheng/archive/2008/09/15/229053.html</link><dc:creator>叶澍?/dc:creator><author>叶澍?/author><pubDate>Mon, 15 Sep 2008 13:53:00 GMT</pubDate><guid>http://www.tkk7.com/yeshucheng/archive/2008/09/15/229053.html</guid><wfw:comment>http://www.tkk7.com/yeshucheng/comments/229053.html</wfw:comment><comments>http://www.tkk7.com/yeshucheng/archive/2008/09/15/229053.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.tkk7.com/yeshucheng/comments/commentRss/229053.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/yeshucheng/services/trackbacks/229053.html</trackback:ping><description><![CDATA[  <p style="text-indent: 21pt"><span style="font-family: 宋体">了解</span>HashMap<span style="font-family: 宋体">原理对于日后的缓存机制多有些认识。在|络中也有很多方面的帖子Q但是很多都是轻描E写,很少有把握的比较准确的信息,在这里试着不妨说解一二?/span></p> <p>    <span style="font-family: 宋体">对于</span>HashMap<span style="font-family: 宋体">主要以键?/span>(key-value)<span style="font-family: 宋体">的方式来体现Q笼l的说就是采?/span>key<span style="font-family: 宋体">值的哈希法来,外加取余最l获取烦引,而这个烦引可以认定是一U地址Q既而把相应?/span>value<span style="font-family: 宋体">存储在地址指向内容中。这栯或许比较概念化,也可能复qC够清楚,来看列式更加清晰Q?/span></p> <div style="border-right: windowtext 0.5pt solid; padding-right: 4pt; border-top: windowtext 0.5pt solid; padding-left: 4pt; background: #d9d9d9; padding-bottom: 1pt; border-left: windowtext 0.5pt solid; padding-top: 1pt; border-bottom: windowtext 0.5pt solid"> <p style="border-right: medium none; padding-right: 0cm; border-top: medium none; padding-left: 0cm; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: medium none">         int   hash=key.hashCode();//------------------------1</p> <p style="border-right: medium none; padding-right: 0cm; border-top: medium none; padding-left: 0cm; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: medium none">         int   index=hash%table.lenth;//table<span style="font-family: 宋体">表示当前对象的长?/span>-----------------------2</p> </div> <p><span style="font-family: 宋体">其实最l就是这两个式子军_了值得存储位置。但是以上两个表辑ּq有Ơ缺。ؓ什么这么说Q例如在</span>key.hashCode()<span style="font-family: 宋体">后可能存在是一个负整数Q你会问Q是啊,那这个时候怎么办呢Q所以在q里需要进一步加强改造式?/span>2<span style="font-family: 宋体">了,修改后的Q?/span></p> <div style="border-right: windowtext 0.5pt solid; padding-right: 4pt; border-top: windowtext 0.5pt solid; padding-left: 4pt; background: #d9d9d9; padding-bottom: 1pt; border-left: windowtext 0.5pt solid; padding-top: 1pt; border-bottom: windowtext 0.5pt solid"> <p style="border-right: medium none; padding-right: 0cm; border-top: medium none; padding-left: 0cm; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: medium none">      int   index=<span style="font-family: 宋体">Q?/span>hash&Ox7FFFFFFF)%table.lenth;</p> </div> <p><span style="font-family: 宋体">到这里又qh了,Z么上面是q样的呢Q对于先前我们谈到在</span>hash<span style="font-family: 宋体">有可能生负数的情况Q这里我们用当前的</span>hash<span style="font-family: 宋体">做一?#8220;?#8221;操作Q在q里需要和</span>int<span style="font-family: 宋体">最大的值相“?#8221;。这L话就可以保证数据的统一性,把有W号的数值给“?#8221;掉。而一般这里我们把二进制的数D{换成</span>16<span style="font-family: 宋体">q制的就变成了:</span>Ox7FFFFFFF<span style="font-family: 宋体">。(注:与操作的方式为,不同?/span>0<span style="font-family: 宋体">Q相同ؓ</span>1<span style="font-family: 宋体">Q。而对?/span>hashCode()<span style="font-family: 宋体">的方法一般有Q?/span></p> <div style="border-right: windowtext 0.5pt solid; padding-right: 4pt; border-top: windowtext 0.5pt solid; padding-left: 4pt; background: #d9d9d9; padding-bottom: 1pt; border-left: windowtext 0.5pt solid; padding-top: 1pt; border-bottom: windowtext 0.5pt solid"> <p style="border-right: medium none; padding-right: 0cm; border-top: medium none; padding-left: 0cm; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: medium none">     public int hashCode(){</p> <p style="border-right: medium none; padding-right: 0cm; border-top: medium none; padding-left: 0cm; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: medium none">                int hash=0,offset,len=count;</p> <p style="border-right: medium none; padding-right: 0cm; border-top: medium none; padding-left: 0cm; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: medium none">                char[] var=value;</p> <p style="border-right: medium none; padding-right: 0cm; border-top: medium none; padding-left: 0cm; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: medium none">               for(int i=0;i<len;i++){</p> <p style="border-right: medium none; padding-right: 0cm; border-top: medium none; padding-left: 0cm; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: medium none">                      h=31*hash+var[offset++];</p> <p style="border-right: medium none; padding-right: 0cm; border-top: medium none; padding-left: 0cm; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: medium none">                }</p> <p style="border-right: medium none; padding-right: 0cm; border-top: medium none; padding-left: 0cm; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: medium none">               return hash;</p> <p style="border-right: medium none; padding-right: 0cm; border-top: medium none; padding-left: 0cm; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: medium none">         }</p> </div> <p style="text-indent: 21pt"><span style="font-family: 宋体">说道q里大家可能会说Q到q里完事了吧。但是你可曾惛_如果数据都采用上面的方式Q最l得到的可能</span>index<span style="font-family: 宋体">会相同怎么办呢Q如果你惛_的话Q那恭喜?/span>!<span style="font-family: 宋体">又增q一步了Q这里就是要说到一个名词:冲突率。是的就是前面说道的一?/span>index<span style="font-family: 宋体">有相同怎么办?数据又该如何存放呢,而且q个在数据量非常庞大的时候这个基率更大。这里按照算法需要明的一点:每个键(</span>key<span style="font-family: 宋体">Q被散列分布CQ何一个数l烦引的可能性相同,而且不取决于其它键分布的位置。这句话怎么理解呢?从概率论的角度,也就是说如果</span>key<span style="font-family: 宋体">的个数达C个极限,每个</span>key<span style="font-family: 宋体">分布的机率都是均{的。更q一步就是:即便</span>key1<span style="font-family: 宋体">不等?/span>key2<span style="font-family: 宋体">也还是可?/span>key1.hashCode()=key2.hashCode()<span style="font-family: 宋体">?/span></p> <p style="text-indent: 21pt"><span style="font-family: 宋体">对于早期的解军_H的Ҏ有折叠法Q?/span>folding)<span style="font-family: 宋体">Q例如我们在做系l的时候有时候会采用部门~号附加到某个单据标号后Q这里比如生一?/span>9<span style="font-family: 宋体">?/span>11<span style="font-family: 宋体">位的~码。通过对半折叠做?/span></p> <p><span style="font-family: 宋体">现在的策略有Q?/span></p> <p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">1.<span style="font: 7pt 'Times New Roman'">       </span><span style="font-family: 宋体">键式散列</span> </p> <p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">2.<span style="font: 7pt 'Times New Roman'">       </span><span style="font-family: 宋体">开攑֜址?/span></p> <p><span style="font-family: 宋体">在了解这两个{略前,我们先定义清楚几个名词解释:</span></p> <div style="border-right: windowtext 0.5pt solid; padding-right: 4pt; border-top: windowtext 0.5pt solid; padding-left: 4pt; background: #d9d9d9; padding-bottom: 1pt; border-left: windowtext 0.5pt solid; padding-top: 1pt; border-bottom: windowtext 0.5pt solid"> <p style="border-right: medium none; padding-right: 0cm; border-top: medium none; padding-left: 0cm; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: medium none">threshold[<span style="font-family: 宋体">阀?/span>]<span style="font-family: 宋体">Q对象大的边界?/span>;</p> <p style="border-right: medium none; padding-right: 0cm; border-top: medium none; padding-left: 0cm; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: medium none">loadFactor[<span style="font-family: 宋体">加蝲因子</span>]=n/m <span style="font-family: 宋体">Q其?/span>n<span style="font-family: 宋体">代表对象元素个数Q?/span>m<span style="font-family: 宋体">表示当前表的容积最大?/span></p> <p style="border-right: medium none; padding-right: 0cm; border-top: medium none; padding-left: 0cm; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: medium none">threshold=(int)table.length*loadFactor</p> </div> <p><span style="font-family: 宋体">清晰了这几个定义Q我们再来看具体的解x?/span></p> <p><span style="font-family: 宋体">键式散列Q?/span></p> <p style="text-indent: 27pt"><span style="font-family: 宋体">我们直接看一个实例,q样更加清晰它的工作方式,从而避免文字定义。我们这里还是来举一个图书编L例子Q下面比如有q样一些编P</span></p> <p style="text-indent: 27pt">                         <span style="color: black">78938</span><span style="color: black">-000</span><span style="color: black">0</span></p> <p style="text-indent: 27pt"><span style="color: black">                         </span>45678-0001</p> <p style="text-indent: 27pt">                         72678-0002</p> <p style="text-indent: 27pt">                         24678-0001</p> <p style="text-indent: 27pt">                         16678-0001</p> <p style="text-indent: 27pt">                         98678-0003</p> <p style="text-indent: 27pt">                         85678-0002</p> <p style="text-indent: 27pt">                         45232-0004</p> <p><span style="font-family: 宋体">步骤Q?/span></p> <p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">1.<span style="font: 7pt 'Times New Roman'">       </span><span style="font-family: 宋体">把编号作?/span>key,<span style="font-family: 宋体">卻I</span>int hash=key.hashCode();</p> <p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">2.<span style="font: 7pt 'Times New Roman'">       </span>int index=hash%<span style="font-family: 宋体">表大;</span></p> <p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">3.<span style="font: 7pt 'Times New Roman'">       </span><span style="font-family: 宋体">逐步按顺序插入对象中</span></p> <p><span style="font-family: 宋体">现在问题出现了:对于~号通过散列法后很可能产生相同的烦引|意味着存在冲突?/span></p> <p style="text-align: center" align="center"><img height="436" alt="" src="http://www.tkk7.com/images/blogjava_net/yeshucheng/111.JPG" width="617" border="0" /></p> <p><span style="font-family: 宋体">解释上面的操作:如果对于</span>key.hashCode()<span style="font-family: 宋体">产生了冲H(比如途中对于插入</span>24678-0001<span style="font-family: 宋体">对于通过哈希法后可能生的</span>index<span style="font-family: 宋体">或许也是</span>501<span style="font-family: 宋体">Q,既而把相应的前驱有相同?/span>index<span style="font-family: 宋体">的对象指向当前引用。这也就是大家认定的单链表方式。以此类?/span>…</p> <p><span style="font-family: 宋体">而这里存在冲H对象的元素攑֜</span>Entry<span style="font-family: 宋体">对象中,</span>Entry<span style="font-family: 宋体">h以下一些属性:</span></p> <p>int hash;</p> <p>Object key;</p> <p>Entry next;</p> <p><span style="font-family: 宋体">对于</span>Entry<span style="font-family: 宋体">对象可以直接追溯到链表数据l构体中查阅?/span></p> <p><span style="font-family: 宋体">开攑֜址法:</span></p> <p style="margin-left: 21pt; text-indent: -21pt; tab-stops: list 21.0pt">1.<span style="font: 7pt 'Times New Roman'">         </span><span style="font-family: 宋体">U性地址探测法:</span></p> <p><span style="font-family: 宋体">如何理解q个概念呢,一句话Q就是通过法规则在对象地址</span>N+1<span style="font-family: 宋体">中查阅找Cؓ</span>NULL<span style="font-family: 宋体">的烦引内宏V?/span></p> <p><span style="font-family: 宋体">处理方式Q如?/span>index<span style="font-family: 宋体">索引与当前的</span>index<span style="font-family: 宋体">有冲H,x当前的烦?/span>index+1<span style="font-family: 宋体">。如果在</span>index+1<span style="font-family: 宋体">已经存在占位现象Q?/span>index+1<span style="font-family: 宋体">的内容不?/span>NULL<span style="font-family: 宋体">Q试图接着</span>index+2<span style="font-family: 宋体">执行。。。直到找到烦引ؓ内容?/span>NULL<span style="font-family: 宋体">的ؓ止。这U处理方式也叫:U性地址探测?/span>(offset-of-1)</p> <p><span style="font-family: 宋体">如果采用U性地址探测法会带来一个效率的不良影响。现在我们来分析q种方式会带来哪些不良因素。大家试想下如果一个非常庞大的数据存储?/span>Map<span style="font-family: 宋体">中,假如在某些记录集中有一些数据非常相|他们产生的烦引在内存的某个块中非常的密集Q,也就是说他们产生的烦引地址是一个连l数|而造成数据成块现象。另一个致命的问题是在数据删除后Q如果再ơ查询可能无法定C一个连l数字,q个又是一个什么概念呢Q例如以下图片就很好的说明开发地址散列如何把数据按照算法插入到对象中:</span></p> <p style="text-align: center" align="center"><img height="502" alt="" src="http://www.tkk7.com/images/blogjava_net/yeshucheng/222.JPG" width="512" border="0" /></p> <p><span style="font-family: 宋体">对于上图的注释步骤说明:</span></p> <p style="line-height: 119%; text-align: center" align="center"><span style="font-family: 宋体">从数?#8220;</span>78938-0000<span style="font-family: 宋体">”开始通过哈希法按顺序依ơ插入到对象中,例如</span>78938-0000<span style="font-family: 宋体">通过?/span></p> <p style="line-height: 119%"><span style="font-family: 宋体">得到烦引ؓ</span>0<span style="font-family: 宋体">Q当前所指内容ؓ</span>NULL<span style="font-family: 宋体">所以直接插入;</span><span style="color: black">45678-0001</span><span style="color: black; font-family: 宋体">同样通过换算得到索引为地址</span><span style="color: black">501</span><span style="color: black; font-family: 宋体">所指内容,当前内容?/span><span style="color: black">NULL</span><span style="color: black; font-family: 宋体">所以也可以插入Q?/span><span style="color: black">72678-0002</span><span style="color: black; font-family: 宋体">得到索引</span><span style="color: black">502</span><span style="color: black; font-family: 宋体">所指内容,当前内容?/span><span style="color: black">NULL</span><span style="color: black; font-family: 宋体">也可以插入;h意当</span><span style="color: black">24678-0001</span><span style="color: black; font-family: 宋体">得到索引也ؓ</span><span style="color: black">501</span><span style="color: black; font-family: 宋体">Q当前地址所指内容ؓ</span><span style="color: black">45678-0001</span><span style="color: black; font-family: 宋体">。即表示当前数据存在冲突Q则直接对地址</span><span style="color: black">501+1=502</span><span style="color: black; font-family: 宋体">所指向内容?/span><span style="color: black">72678-0002</span><span style="color: black; font-family: 宋体">不ؓ</span><span style="color: black">NULL</span><span style="color: black; font-family: 宋体">也不允许插入Q再ơ对索引</span><span style="color: black">502+1=503</span><span style="color: black; font-family: 宋体">所指内容ؓ</span><span style="color: black">NULL</span><span style="color: black; font-family: 宋体">允许插入。。。依ơ类推只要对于烦引存在冲H现象,则逐次下移位知道烦引地址所指ؓ</span><span style="color: black">NULL</span><span style="color: black; font-family: 宋体">Q如果烦引不冲突则还是按照算法放入内宏V对于这L对象是一U插入方式,接下来就是我们的删除</span><span style="color: black">(remove)</span><span style="color: black; font-family: 宋体">Ҏ了。按照常理对于删除,方式基本区别不大。但是现在问题又出现了,如果删除的某个数据是一个存在冲H烦引的内容Q带来后l的问题又会接踵而来。那是什么问题呢Q我们还是同h看看囄的描qͼ对于?/span><span style="color: black">-2</span><span style="color: black; font-family: 宋体">中如果删?/span><span style="color: black">(remove)</span><span style="color: black; font-family: 宋体">数据</span><span style="color: black">24678-0001</span><span style="color: black; font-family: 宋体">的方法如下图所C:</span></p> <p style="line-height: 119%; text-align: center" align="center"><img height="502" alt="" src="http://www.tkk7.com/images/blogjava_net/yeshucheng/333.JPG" width="512" border="0" /></p> <p style="line-height: 119%"><span style="font-family: 宋体">对于我们会想当然的觉得只要把指向数据|ؓ</span>NULL<span style="font-family: 宋体">可?/span>,<span style="font-family: 宋体">q样的做法对于删除来说当然是没有问题的。如果再ơ定位检索数?/span>16678-0001<span style="font-family: 宋体">不会成功Q因个时候以前的链\已经堵上了,但是需要检索的数据事实上又存在。那我们如何来解册个问题呢Q对?/span>JDK<span style="font-family: 宋体">中的</span>Entry<span style="font-family: 宋体">cM的方法存在一个:</span>boolean markedForRemoval;<span style="font-family: 宋体">它就是一个典型的删除标志位,对于对象中如果需要删除时Q我们只是对于它做一?#8220;软删?#8221;即置一个标志位?/span>true<span style="font-family: 宋体">可以。而插入时Q默认状态ؓ</span>false<span style="font-family: 宋体">可以。这L话就变成以下图所C:</span></p> <p style="line-height: 119%; text-align: center" align="center"><img height="502" alt="" src="http://www.tkk7.com/images/blogjava_net/yeshucheng/444.JPG" width="512" border="0" /></p> <p style="line-height: 119%"><span style="font-family: 宋体">通过以上方式更好的解军_H地址删除数据无法索其他链路数据问题了?/span></p> <p style="margin-left: 21pt; text-indent: -21pt; line-height: 119%; tab-stops: list 21.0pt">2.<span style="font: 7pt 'Times New Roman'">         </span><span style="font-family: 宋体">双散列(余商法)</span></p> <p style="margin-left: 21pt; text-indent: 21pt; line-height: 119%"><span style="font-family: 宋体">在了解开攑֜址散列的时候我们一直在说解x法,但是大家都知道一个数据结构的完善更多的是需要高效的法。这当中我们却没有涉及到。接下来我们来看看在开攑֜址散列中它存在的一些不以及如何改善这LҎQ既而达到无论是在方法的解决上还是在法的复杂度上更加达到高效的Ҏ?/span></p> <p style="margin-left: 21pt; text-indent: 21pt; line-height: 119%"><span style="font-family: 宋体">在图</span>2-1<span style="font-family: 宋体">中类D样一些数据插入进对象Q存在冲H采用不断移位加一的方式,直到扑ֈ不ؓ</span>NULL<span style="font-family: 宋体">内容的烦引地址。也正是׃q样一U可能加大了旉上的变慢。大家是否注意到像图q样一些数据目前呈现出一U连l烦引的插入Q而且是一U成块是的数据。如果数据量非常的庞大,或许q种可能性更大。尽它解决了冲H,但是对于数据索的旉度来_我们是不敢想象的。所有分布到同一个烦?/span>index<span style="font-family: 宋体">上的</span>key<span style="font-family: 宋体">保持相同的\径:</span>index,index+1,index+2…<span style="font-family: 宋体">依此cL。更加糟p的是烦引键值的索需要从索引开始查找。正是这L原因Q对于线性探索法我们需要更q一步的改进。而刚才所描述q种成块出现的数据也定义成Q簇。而这样一U现象称之ؓQ主现象?/span></p> <p style="line-height: 119%"><span style="font-family: 宋体">Q主:是冲突处理允许加速增长时出现的现象)而开攑ּ地址冲突也是允许ȝ现象产生的。那我们如何来避免这U主现象呢Q这个方式就是我们要来说明的Q双散列解决冲突法了。主要的方式为:</span></p> <p style="background: #e5e5e5; margin-left: 21pt; text-indent: -21pt; line-height: 119%; tab-stops: list 21.0pt"><span style="font-family: Wingdings">u<span style="font: 7pt 'Times New Roman'">       </span></span>int hash=key.hasCode();</p> <p style="background: #e5e5e5; margin-left: 21pt; text-indent: -21pt; line-height: 119%; tab-stops: list 21.0pt"><span style="font-family: Wingdings">u<span style="font: 7pt 'Times New Roman'">       </span></span>int index=(hash&Ox7FFFFFFF)%table.length;</p> <p style="background: #e5e5e5; margin-left: 21pt; text-indent: -21pt; line-height: 119%; tab-stops: list 21.0pt"><span style="font-family: Wingdings">u<span style="font: 7pt 'Times New Roman'">       </span></span><span style="font-family: 宋体">按照以上方式得到索引存在冲突Q则开始对当前索引UMQ而移位方式ؓQ?/span></p> <p style="background: #e5e5e5; line-height: 119%">        offset=(hash&Ox7FFFFFFF)/table.length;</p> <p style="background: #e5e5e5; margin-left: 21pt; text-indent: -21pt; line-height: 119%; tab-stops: list 21.0pt"><span style="font-family: Wingdings">u<span style="font: 7pt 'Times New Roman'">       </span></span><span style="font-family: 宋体">如果W一ơ移位还存在同样的冲H,则l:当前冲突索引位置Q烦引号</span>+<span style="font-family: 宋体">余数Q?/span>%<span style="font-family: 宋体">?/span>.length</p> <p style="background: #e5e5e5; margin-left: 21pt; text-indent: -21pt; line-height: 119%; tab-stops: list 21.0pt"><span style="font-family: Wingdings">u<span style="font: 7pt 'Times New Roman'">       </span></span><span style="font-family: 宋体">如果存在的余数恰好是表的倍数Q则作偏UM|ؓ一下移Q依此类?/span></p> <p style="text-indent: 21pt; line-height: 119%"><span style="font-family: 宋体">q样双散列冲H处理就避免了主现象。至?/span>HashSet<span style="font-family: 宋体">的原理基本和它是一致的Q这里不再复q。在q里其实q是主要说了一些简单的解决方式Q而且都是在一些具体参数满x件下的说明,像一旦数据超q初始D需?/span>rehash<span style="font-family: 宋体">Q加载因子一旦大?/span>1.0<span style="font-family: 宋体">是何U情늭{。还有很多问题都可以值得我们更加q一步讨论的Q比如:?/span>java.util.HashMap<span style="font-family: 宋体">中的加蝲因子Z么会?/span>0.75<span style="font-family: 宋体">Q而它默认的初始大ؓ什么又?/span>16<span style="font-family: 宋体">{等q些问题都还值得说明。要说明q些问题可能又需要更加详的说明清楚?/span></p> <img src ="http://www.tkk7.com/yeshucheng/aggbug/229053.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/yeshucheng/" target="_blank">叶澍?/a> 2008-09-15 21:53 <a href="http://www.tkk7.com/yeshucheng/archive/2008/09/15/229053.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://kanboy.com" target="_blank">avۺavav</a>| <a href="http://amgzh.com" target="_blank">պƵһ</a>| <a href="http://7s8s.com" target="_blank">޹av߲</a>| <a href="http://mtsp5.com" target="_blank">߲Ƶ</a>| <a href="http://www55nana.com" target="_blank">˼˼99re66߾Ʒѹۿ</a>| <a href="http://ghdc5.com" target="_blank">AëƬAĻ </a>| <a href="http://cpsc-test.com" target="_blank">þAV</a>| <a href="http://626393.com" target="_blank">ɫŮһ˿</a>| <a href="http://zfjhw.com" target="_blank">ƵƷ</a>| <a href="http://18yinren.com" target="_blank">ëƬƵۿ</a>| <a href="http://qqcao7.com" target="_blank">ھƷ鶹վ91鶹</a>| <a href="http://ivy-fund.com" target="_blank">պƵ</a>| <a href="http://cn-taoqigui.com" target="_blank">߹Ӱվ</a>| <a href="http://zjtuntex.com" target="_blank">һѹۿձwwwƵ</a>| <a href="http://zhaoxinwo.com" target="_blank">ƷAV鶹 </a>| <a href="http://newbuybay.com" target="_blank">Ұѹۿ</a>| <a href="http://cjsyw123.com" target="_blank">ѹ99þþ㽶</a>| <a href="http://av-fantasy.com" target="_blank">㽶ѿһ</a>| <a href="http://misiranim.com" target="_blank">һѹۿձwwwƵ</a>| <a href="http://tsxyhq.com" target="_blank">ձƵѹۿ</a>| <a href="http://fjwkjx.com" target="_blank">պƵƵ </a>| <a href="http://bdykdq.com" target="_blank">߲ݹ޾ƷƷ </a>| <a href="http://nibayuan.com" target="_blank">þþþù</a>| <a href="http://dzhyyy.com" target="_blank">Ʒһ</a>| <a href="http://857995.com " target="_blank">߾Ʒһ㽶</a>| <a href="http://786087.com" target="_blank">ִˬƵ</a>| <a href="http://532342.com" target="_blank">պ߹ۿƵ</a>| <a href="http://35469642.com" target="_blank">ѸAëƬ߲</a>| <a href="http://jjwgzx.com" target="_blank">ӾƷ</a>| <a href="http://zhuoyueyc.com" target="_blank">ɫʹɫӰԺ</a>| <a href="http://shelaoban.com" target="_blank">ŷ޹SUV</a>| <a href="http://zzyqr.com" target="_blank">ŮƵaŮȫƤ</a>| <a href="http://zj1069.com" target="_blank">ƷŮͬһѲ</a>| <a href="http://34pmpm.com" target="_blank">avרavëƬ</a>| <a href="http://rr7733.com" target="_blank">AVרAV</a>| <a href="http://dzhyyy.com" target="_blank">ŷŮƬѲƵ</a>| <a href="http://hdznzdh.com" target="_blank">caopornѹ</a>| <a href="http://9522952.com" target="_blank">99ƷƷ</a>| <a href="http://dou18.com" target="_blank">99þùĻ</a>| <a href="http://942woool.com" target="_blank">Ѷ</a>| <a href="http://www1688mz.com" target="_blank">ĻѸ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>