??xml version="1.0" encoding="utf-8" standalone="yes"?>BlogJava-黑灵客栈 http://www.dentisthealthcenter.com/mstar/黑灵的没啥技术含量的技术博? -> http://zjumty.iteye.com zh-cn Thu, 07 Dec 2023 09:30:52 GMT Thu, 07 Dec 2023 09:30:52 GMT 60 在传输层上压~WebService的请求和响应 http://www.dentisthealthcenter.com/mstar/archive/2013/06/23/400884.html黑灵 黑灵 Sun, 23 Jun 2013 13:45:00 GMT http://www.dentisthealthcenter.com/mstar/archive/2013/06/23/400884.html http://www.dentisthealthcenter.com/mstar/comments/400884.html http://www.dentisthealthcenter.com/mstar/archive/2013/06/23/400884.html#Feedback 1 http://www.dentisthealthcenter.com/mstar/comments/commentRss/400884.html http://www.dentisthealthcenter.com/mstar/services/trackbacks/400884.html 阅读全文 ]]> 在MongoDB里实现@环序列功? http://www.dentisthealthcenter.com/mstar/archive/2013/04/26/398469.html黑灵 黑灵 Fri, 26 Apr 2013 14:57:00 GMT http://www.dentisthealthcenter.com/mstar/archive/2013/04/26/398469.html http://www.dentisthealthcenter.com/mstar/comments/398469.html http://www.dentisthealthcenter.com/mstar/archive/2013/04/26/398469.html#Feedback 1 http://www.dentisthealthcenter.com/mstar/comments/commentRss/398469.html http://www.dentisthealthcenter.com/mstar/services/trackbacks/398469.html
环境是这LQ服务器是用Java做的Q?数据库是MongoDB
需求是q样的:我们的系l里要生成一个唯一IDQ前面的部分有一定的格式Qƈ和时间关联, _到微U,考虑到同一微秒内有可能存在q发情况Q?
所以后面在加两位序列号Q?pȝ需要定义ؓ1毫秒内的q发于100个,所以后面两位就够用了?
Java服务器端有多台机器都可以用来生成q个唯一IDQ所以需要在不同的机器上不能生成相同的序列号Q所以需要在某一点上做全局的范围同步来保存q序?
L唯一性?其实如果不考虑需求里的唯一ID是有一定意义的格式的,
用UUID或MongoDB的ObjectId都是更好的选择Q完全不需要在某一点上q行同步Q性能会更好?/p>
q个可以生成序列L点, 我们可以做一个序列号生成服务器来对应Q?也可以用数据库来对应?
单单个简单的功能准备一个服务器来做昄不合适?但是我们用的MongoDBq没有类gMySQL或Oracle中的SELECT FOR
UPDATEq样的锁机制?所以没有办法简单的对这个序列号做原子操作?
但是MongoDB的对单个documentq行update操作中有很是h原子性的Q?例如
$set $unset $inc $push $pushAll $pull $pullAll
我们可以利用q些原子操作Q在数据库层以乐观锁的Ş式来实现循环序列字段。ؓ了方便调用我把这D逻辑做成数据库中的Javascript函数?cM与MySQL中的存储q程?/p>
首先我们需要一个collection来存攑ֺ列号Qƈ寚w要的需要的序列可行初始化。我们叫它counters?/p>
db.counters.save({_id: "SerialNo1" , val:0, maxval:99})
然后我们想system.js里添加一个Javascript函数
db.system.js.save({_id: "getNextUniqueSeq" , value:function (keyName) { var seqObj = db.counters.findOne({_id:keyName}); if (seqObj == null ) { print("can not find record with key: " + keyName); return -1; } var maxVal = seqObj.maxval; var curVal = seqObj.val; while ( true ){ if (curVal >= maxVal){ db.counters.update({_id : keyName, val : curVal}, { $set : { val : 0 }}, false , false ); var err = db.getLastErrorObj(); if ( err && err.code ) { print( "unexpected error reset data: " + tojson( err ) ); return -2; } else if (err.n == 0){ print("fail to reset value: " ); } seqObj = db.counters.findOne({_id:keyName}); maxVal = seqObj.maxval; curVal = seqObj.val; continue ; } db.counters.update({_id : keyName, val : curVal}, { $inc : { val : 1 }}, false , false ); var err = db.getLastErrorObj(); if ( err && err.code ) { print( "unexpected error inc val: " + tojson( err ) ); return -3; } else if (err.n == 0){ print("fail to inc value: " ); seqObj = db.counters.findOne({_id:keyName}); maxVal = seqObj.maxval; curVal = seqObj.val; continue ; } else { var retVal = curVal + 1; print("success to get seq : " + retVal); return retVal; } } } });
上面q段会把指定的序列号的val?1Q如果val辑ֈ上限则从0开始。所以叫循环序列?/p>
其实上面的实现在原理上和Java里的AtomicIntegerpd的功能实现是cM的,利用循环重试和原子性的CAS来实现。这U实现方式在多线E的环境里由于锁QMonitorQ的范围很小Q所以ƈ发性上比排他锁要好一些?/p>
下面我们用Java来测试一下这个函数的正确性?卛_多线E的情况下会不会得到重复的序列号?/p>
W一个测试,val=0Q?maxval=2000Q?Java?0个线E每个线E@环调?00ơ??000ơ?所以正的情况下,??999应该每个数字只出Cơ?/p>
@Test public void testGetNextUniqueSeq1() throws Exception { final int THREAD_COUNT = 20 ; final int LOOP_COUNT = 100 ; Mongo mongoClient = new Mongo( "172.17.2.100" , 27017 ); DB db = mongoClient.getDB("im" ); db.authenticate("imadmin" , "imadmin" .toCharArray()); BasicDBObject q = new BasicDBObject(); q.put("_id" , "UNIQUE_KEY" ); BasicDBObject upd = new BasicDBObject(); BasicDBObject set = new BasicDBObject(); set.put("val" , 0 ); set.put("maxval" , THREAD_COUNT * LOOP_COUNT); upd.put("$set" , set); db.getCollection("counters" ).update(q, upd); Thread[] threads = new Thread[THREAD_COUNT]; final int [][] results = new int [THREAD_COUNT][LOOP_COUNT]; for ( int i = 0 ; i < THREAD_COUNT; i++) { final int temp_i = i; threads[i] = new Thread( "" + i) { @Override public void run() { try { Mongo mongoClient = new Mongo( "172.17.2.100" , 27017 ); DB db = mongoClient.getDB("im" ); db.authenticate("imadmin" , "imadmin" .toCharArray()); for ( int j = 0 ; j < LOOP_COUNT; j++) { Object result = db.eval("getNextUniqueSeq(\"UNIQUE_KEY\")" ); System.out.printf("Thread %s, seq=%d\n" , Thread.currentThread().getName(), ((Double) result).intValue()); results[temp_i][j] = ((Double) result).intValue(); } } catch (UnknownHostException e) { e.printStackTrace(); } } }; } for (Thread thread : threads) { thread.start(); } for (Thread thread : threads) { thread.join(); } for ( int num = 1 ; num <= LOOP_COUNT * THREAD_COUNT; num++) { int times = 0 ; for ( int j = 0 ; j < THREAD_COUNT; j++) { for ( int k = 0 ; k < LOOP_COUNT; k++) { if (results[j][k] == num) times++; } } assertEquals(1 , times); } }
然后我们再测试一下@环的情况?val=0, maxval=99?同样是Java?0个线E每个线E@环调?00ơ??000ơ。这ơ从0?9的数字每个应该取?0ơ?/p>
@Test public void testGetNextUniqueSeq2() throws Exception { final int THREAD_COUNT = 20 ; final int LOOP_COUNT = 100 ; Mongo mongoClient = new Mongo( "172.17.2.100" , 27017 ); DB db = mongoClient.getDB("im" ); db.authenticate("imadmin" , "imadmin" .toCharArray()); BasicDBObject q = new BasicDBObject(); q.put("_id" , "UNIQUE_KEY" ); BasicDBObject upd = new BasicDBObject(); BasicDBObject set = new BasicDBObject(); set.put("val" , 0 ); set.put("maxval" , LOOP_COUNT); upd.put("$set" , set); db.getCollection("counters" ).update(q, upd); Thread[] threads = new Thread[THREAD_COUNT]; final int [][] results = new int [THREAD_COUNT][LOOP_COUNT]; for ( int i = 0 ; i < THREAD_COUNT; i++) { final int temp_i = i; threads[i] = new Thread( "" + i) { @Override public void run() { try { Mongo mongoClient = new Mongo( "172.17.2.100" , 27017 ); DB db = mongoClient.getDB("im" ); db.authenticate("imadmin" , "imadmin" .toCharArray()); for ( int j = 0 ; j < LOOP_COUNT; j++) { Object result = db.eval("getNextUniqueSeq(\"UNIQUE_KEY\")" ); System.out.printf("Thread %s, seq=%d\n" , Thread.currentThread().getName(), ((Double) result).intValue()); results[temp_i][j] = ((Double) result).intValue(); } } catch (UnknownHostException e) { e.printStackTrace(); } } }; } for (Thread thread : threads) { thread.start(); } for (Thread thread : threads) { thread.join(); } for ( int num = 1 ; num <= LOOP_COUNT; num++) { int times = 0 ; for ( int j = 0 ; j < THREAD_COUNT; j++) { for ( int k = 0 ; k < LOOP_COUNT; k++) { if (results[j][k] == num) times++; } } assertEquals(20 , times); } }
q个试跑了几次都是正确的?/p>
׃没有可以q行Ҏ其他的实现方式(例如排他锁)所以没有做性能试?/p>
写在最后?虽然MongoDB支持cM于存储过E的Stored
JavascriptQ但是其实不使用q个来解军_杂问题。主要原因是没法调试Q维护v来太不方ѝ而且?.4之前MongoDBҎ务端
Javascript支持q不是很好,
一个mongodq程同时只能执行一DJavascript。如果能在应用层解决掉还是在应用层里实现逻辑比较好?/p>
]]> 输出debug信息到postfix的log http://www.dentisthealthcenter.com/mstar/archive/2013/04/26/398459.html黑灵 黑灵 Fri, 26 Apr 2013 11:25:00 GMT http://www.dentisthealthcenter.com/mstar/archive/2013/04/26/398459.html http://www.dentisthealthcenter.com/mstar/comments/398459.html http://www.dentisthealthcenter.com/mstar/archive/2013/04/26/398459.html#Feedback 0 http://www.dentisthealthcenter.com/mstar/comments/commentRss/398459.html http://www.dentisthealthcenter.com/mstar/services/trackbacks/398459.html /etc/postfix/main.cf
debug_peer_list = example.com debug_peer_level = 2
/etc/postfix/master.cf
smtp inet n - n - - smtpd -v
]]>Java里的CompareAndSet(CAS) http://www.dentisthealthcenter.com/mstar/archive/2013/04/24/398351.html黑灵 黑灵 Wed, 24 Apr 2013 09:20:00 GMT http://www.dentisthealthcenter.com/mstar/archive/2013/04/24/398351.html http://www.dentisthealthcenter.com/mstar/comments/398351.html http://www.dentisthealthcenter.com/mstar/archive/2013/04/24/398351.html#Feedback 0 http://www.dentisthealthcenter.com/mstar/comments/commentRss/398351.html http://www.dentisthealthcenter.com/mstar/services/trackbacks/398351.html
Atomic
从JDK5开? java.util.concurrent包里提供了很多面向ƈ发编E的c? 使用q些cd多核CPU的机器上会有比较好的性能. 主要原因是这些类里面大多使用(p|-重试方式?乐观锁而不是synchronized方式的悲观锁. 今天有时间跟t了一下AtomicInteger的incrementAndGet的实? 本h对ƈ发编E也不是特别了解, 在这里就是做个笔? 方便以后再深入研I? 1. incrementAndGet的实?br /> public final int incrementAndGet() { for (;;) { int current = get(); int next = current + 1 ; if (compareAndSet(current, next)) return next; } }
首先可以看到他是通过一个无限@?spin)直到increment成功为止. 循环的内Ҏ 1.取得当前?br />2.计算+1后的?br />3.如果当前D有效(没有?的话讄那个+1后的?br />4.如果讄没成?当前值已l无效了卌别的U程改过?, 再从1开? 2. compareAndSet的实?br /> public final boolean compareAndSet( int expect, int update) { return unsafe.compareAndSwapInt( this , valueOffset, expect, update); }
直接调用的是UnSafeq个cȝ compareAndSwapIntҎ 全称?/span> sun.misc.Unsafe. q个cLOracle(Sun)提供的实? 可以在别的公司的JDK里就不是q个cM 3. compareAndSwapInt的实?br /> /** * Atomically update Java variable to <tt>x</tt> if it is currently * holding <tt>expected</tt>. * @return <tt>true</tt> if successful */ public final native boolean compareAndSwapInt(Object o, long offset, int expected, int x);
可以看到, 不是用Java实现? 而是通过JNI调用操作pȝ的原生程? 4. compareAndSwapInt的native实现 如果你下载了OpenJDK的源代码的话在hotspot\src\share\vm\prims\目录下可以找到unsafe.cppUNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv * env, jobject unsafe , jobject obj, jlong offset, jint e, jint x)) UnsafeWrapper( " Unsafe_CompareAndSwapInt " ); oop p = JNIHandles::resolve(obj); jint * addr = (jint * ) index_oop_from_field_offset_long(p, offset); return (jint)(Atomic::cmpxchg(x, addr, e)) == e; UNSAFE_END
可以看到实际上调?/span>Atomiccȝ cmpxchgҎ. 5. Atomic?/span> cmpxchg q个cȝ实现是跟操作pȝ有关, 跟CPU架构也有? 如果是windows下x86的架?br />实现在hotspot\src\os_cpu\windows_x86\vm\目录的atomic_windows_x86.inline.hpp文g?br />inline jint Atomic::cmpxchg (jint exchange_value, volatile jint * dest, jint compare_value) { // alternative for InterlockedCompareExchange int mp = os::is_MP(); __asm { mov edx, dest mov ecx, exchange_value mov eax, compare_value LOCK_IF_MP(mp) cmpxchg dword ptr [edx], ecx } }
在这里可以看到是用嵌入的汇编实现? 关键CPU指o?/span> cmpxchg 到这里没法再往下找代码? 也就是说CAS的原子性实际上是CPU实现? 其实在这一点上q是有排他锁? 只是比v用synchronized, q里的排他时间要短的? 所以在多线E情况下性能会比较好. 代码里有?/span> alternative for InterlockedCompareExchange q个 InterlockedCompareExchange是WINAPI里的一个函? 做的事情和上面这D|~是一L http://msdn.microsoft.com/en-us/library/windows/desktop/ms683560%28v=vs.85%29.aspx 6. 最后再贴一下x86的cmpxchg指定Opcode CMPXCHG CPU: I486+
Type of Instruction: User
Instruction: CMPXCHG dest, src
Description: Compares the accumulator with dest. If equal the "dest"
is loaded with "src", otherwise the accumulator is loaded
with "dest".
Flags Affected: AF, CF, OF, PF, SF, ZF
CPU mode: RM,PM,VM,SMM
+++++++++++++++++++++++
Clocks:
CMPXCHG reg, reg 6
CMPXCHG mem, reg 7 (10 if compartion fails)
]]> Apache Mina 中文文译 - Ҏ?/title> http://www.dentisthealthcenter.com/mstar/archive/2013/04/23/398309.html黑灵 黑灵 Tue, 23 Apr 2013 14:02:00 GMT http://www.dentisthealthcenter.com/mstar/archive/2013/04/23/398309.html http://www.dentisthealthcenter.com/mstar/comments/398309.html http://www.dentisthealthcenter.com/mstar/archive/2013/04/23/398309.html#Feedback 0 http://www.dentisthealthcenter.com/mstar/comments/commentRss/398309.html http://www.dentisthealthcenter.com/mstar/services/trackbacks/398309.html http://mina.apache.org/mina-project/features.html MINA是一个简单的却有功能丰富的网l应用程序框Ӟ 它提供如下特性:通过Java NIO实现 TCP/IP & UPD/IP通信 通过Filter接口实现扩展点;cM与Servlet的Filter 利用Java5的SSLEngine实现的开即用的SSL,TLS, StartTLS功能 可以整合qPicoContainer和Spring{常用容?/li> ]]> Apache Mina 中文文译 - 概述 http://www.dentisthealthcenter.com/mstar/archive/2013/04/22/398241.html黑灵 黑灵 Mon, 22 Apr 2013 15:13:00 GMT http://www.dentisthealthcenter.com/mstar/archive/2013/04/22/398241.html http://www.dentisthealthcenter.com/mstar/comments/398241.html http://www.dentisthealthcenter.com/mstar/archive/2013/04/22/398241.html#Feedback 0 http://www.dentisthealthcenter.com/mstar/comments/commentRss/398241.html http://www.dentisthealthcenter.com/mstar/services/trackbacks/398241.html 原文链接Qhttp://mina.apache.org/mina-project/index.html Apache MINA 是一个网l应用框Ӟ 它可以帮助你单容易的开发高性能Q高可扩展性的|络应用E序。Apache MINA底层利用Java NIO实现Q在TCP/IP和UPD/IP{传输层上提供一个抽象的Z事g驱动的异步API?br /> Apache MINA一般被UCؓQ?br />管如此QApache MINA要提供的比上面说的多得多?你可以看一下它的功能特性列表, 利用q些Ҏ你可以快速开发网l应用程序, 你还可以看一下h们是怎么说MINA的?请下载MINA的包Q尝试一下快速开始指南, 览一下FAQ或者加入我们的C?br /> Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at . http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ]]> Properties.storeToXMLҎ抛出I指针哦! http://www.dentisthealthcenter.com/mstar/archive/2013/04/19/398100.html黑灵 黑灵 Fri, 19 Apr 2013 08:42:00 GMT http://www.dentisthealthcenter.com/mstar/archive/2013/04/19/398100.html http://www.dentisthealthcenter.com/mstar/comments/398100.html http://www.dentisthealthcenter.com/mstar/archive/2013/04/19/398100.html#Feedback 0 http://www.dentisthealthcenter.com/mstar/comments/commentRss/398100.html http://www.dentisthealthcenter.com/mstar/services/trackbacks/398100.html cM下面q段代码: @Test(expected = IOException. class ) public void testPropertiesStoreToXml() throws IOException { Properties props = new Properties(); props.put( " key1 " , true ); ByteArrayOutputStream baos = new ByteArrayOutputStream(); props.storeToXML(baos, null ); String xml = new String(baos.toByteArray()); Assert.fail( " should not go to here " ); }
在生成XML的时候会抛出IOException. Dq个IOException的是做XMLTransform的时候出CNullPointerException 感觉很奇? 调试qProperties的代码看了一? public String getProperty(String key) { Object oval = super .get(key); String sval = (oval instanceof String) ? (String)oval : null ; return ((sval == null ) && (defaults != null )) ? defaults.getProperty(key) : sval; }
原来Propertiesq货, 不是String的属性一码色的返回NULL? l果在XMLTransform的时? 直接对这个NULLq行Ҏ调用. 后来看了一下Properties文, Propertiesl承至Hashtable, 所以有put和putAll之类的方? 但是不徏议? 因ؓq些Ҏ不限定Stringcd. 推荐使用setPropertyҎ, q个Ҏ的g定是String.Because Properties
inherits from Hashtable
, the
put
and putAll
methods can be applied to a
Properties
object. Their use is strongly discouraged as they
allow the caller to insert entries whose keys or values are not
Strings
. The setProperty
method should be used
instead. If the store
or save
method is called
on a "compromised" Properties
object that contains a
non-String
key or value, the call will fail. Similarly,
the call to the propertyNames
or list
method
will fail if it is called on a "compromised" Properties
object that contains a non-String
key.
OK,我承认是我不好好看文就用了. 但是我脚的如果你把非String的D用一下toString再用不是更好吗? ]]>关于spring-mvc的InitBinder注解的参?/title> http://www.dentisthealthcenter.com/mstar/archive/2013/04/17/397945.html黑灵 黑灵 Tue, 16 Apr 2013 16:42:00 GMT http://www.dentisthealthcenter.com/mstar/archive/2013/04/17/397945.html http://www.dentisthealthcenter.com/mstar/comments/397945.html http://www.dentisthealthcenter.com/mstar/archive/2013/04/17/397945.html#Feedback 2 http://www.dentisthealthcenter.com/mstar/comments/commentRss/397945.html http://www.dentisthealthcenter.com/mstar/services/trackbacks/397945.html 比如讄Validator? 我一直在惌不能为每个Request或者每个ActionҎ单独讄Validator?br />也就是说Controller里有多个被@InitBinder标注的方法?在不同的Action时被分别调用?br /> 我注意到了@InitBinder的value参数Q?br /> api docs里是q样描述的: The names of command/form attributes and/or request parameters
that this init-binder method is supposed to apply to.
Default is to apply to all command/form attributes and all request parameters
processed by the annotated handler class. Specifying model attribute names or
request parameter names here restricts the init-binder method to those specific
attributes/parameters, with different init-binder methods typically applying to
different groups of attributes or parameters.
是乎是可以针对不同的Form对象或命令调用不同的InitBinderҎ?/p>
于是我写了下面的Controller试了一?/p>
@Controller public class HomeController { private static final Logger logger = LoggerFactory.getLogger(HomeController. class ); @InitBinder( " action1 " ) public void initBinder1(WebDataBinder binder){ logger.info( " initBinder1 " ); } @InitBinder( " action2 " ) public void initBinder2(WebDataBinder binder){ logger.info( " initBinder2 " ); } /** * Simply selects the home view to render by returning its name. */ @RequestMapping(value = " / " , method = RequestMethod.GET) public String home(Model model) { Date date = new Date(); DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG); String formattedDate = dateFormat.format(date); model.addAttribute( " serverTime " , formattedDate ); return " home " ; } /** * Simply selects the home view to render by returning its name. */ @RequestMapping(value = " /doit " , method = RequestMethod.POST, params = " action1 " ) public String doit1(@RequestParam( " value1 " ) int value1, @RequestParam( " action1 " ) String action, Model model) { logger.info( " value1={} " ,value1); Date date = new Date(); DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG); String formattedDate = dateFormat.format(date); model.addAttribute( " serverTime " , formattedDate ); return " home " ; } /** * Simply selects the home view to render by returning its name. */ @RequestMapping(value = " /doit " , method = RequestMethod.POST, params = " action2 " ) public String doit2(@RequestParam( " value1 " ) int value1, @RequestParam( " action2 " ) String action, Model model) { logger.info( " value1={} " ,value1); Date date = new Date(); DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG); String formattedDate = dateFormat.format(date); model.addAttribute( " serverTime " , formattedDate ); return " home " ; } }
画面上的Form是这L
< form action ="doit" method ="post" enctype ="application/x-www-form-urlencoded" > < input type ="text" name ="value1" value ="100" /> < input type ="submit" name ="action1" value ="Action1" /> < input type ="submit" name ="action2" value ="Action2" /> </ form >
我的意愿是如果画面上Q点击action1按钮择调用initBinder1Ҏ?如果点击action2按钮则调用initBinder2Ҏ?/p>
实际上也实是这L?
当点击action1Ӟlogger.info( " initBinder1 " ); 会执?/span>
当点击action2是,logger.info( " initBinder2 " ); 会执?/span>
是乎是可以实现“每个ActionҎ单独讄Validator”这个目的?/p>
但是其实q不是这L?/p>
我调式进MInitBinder相关的源代码InitBinderDataBinderFactoryQ?l果发现它只是在对actionq个参数l定的时候调用了上面q个ҎQ?对value1l定的时候那个方法都没有调用。而我们常常要解决的是对同一个参数对于不同的action应用不同的Validator?
所以目前还是没有好的方法能直接解决q个问题Q?/p>
也许我们可以自己实现一个DataBinderFactory来解册个问题?/p>
]]> KMP法里的next函数是怎么得到的? http://www.dentisthealthcenter.com/mstar/archive/2013/04/14/397824.html黑灵 黑灵 Sun, 14 Apr 2013 15:24:00 GMT http://www.dentisthealthcenter.com/mstar/archive/2013/04/14/397824.html http://www.dentisthealthcenter.com/mstar/comments/397824.html http://www.dentisthealthcenter.com/mstar/archive/2013/04/14/397824.html#Feedback 0 http://www.dentisthealthcenter.com/mstar/comments/commentRss/397824.html http://www.dentisthealthcenter.com/mstar/services/trackbacks/397824.html 也就是这?p?p?p⑶?.p(k-1Q?= ' p(j-k+1Qp(j-k+2Q……p(j-1Q’?Z么找到这个k以后用k的元素比较字W串中ip了?br /> 现在扑ֈ一个最接近明白的就是百度百U上?br /> 假设 MQs: ‘s?s?s?……s(nQ?; 模式?Qp: ‘p?p?p⑶?.p(mQ?br />把课本上的这一D늜完后Ql?br />现在我们假设 MWi个字W与模式串的Wj(j<=mQ个字符‘失配’后Q主串第i个字W与模式串的Wk(k<jQ个字符l箋比较 此时Qs(iQ≠p(jQ,?br />MQs⑴…?s(i-j+1Q…?s(i-1Q?s(i) ………? || Q相配) || ≠(失配Q?br />匚wԌp?...........p(j-1Q?p(j) 由此Q我们得到关pdQ?br />‘p?p?p⑶?.p(j-1Q?= ?s(i-j+1Q……s(i-1Q?br />׃s(iQ≠p(jQ,接下来s(iQ将与p(kQl比较,则模式串中的前(k-1Q个字符的子串必L下列关pdQƈ且不可能存在 k?gt;k 满下列关系式:Qk<j), ‘p?p?p⑶?.p(k-1Q?= ?s(i-k+1Qs(i-k+2Q……s(i-1Q?br />卻I MQs⑴……s(i-k +1Q?s(i-k +2Q?……s(i-1Q?s(i) ………? || Q相配) || ||Q有待比较) 匚wԌp?p?…?.... p(k-1Q?p(k) 现在我们把前面ȝ的关pȝ合一?br />有: s⑴…s(i-j +1Q?s(i-k +1Q?s(i-k +2Q?…?s(i-1Q?s(i) …?br />|| Q相配) || || || ≠(失配Q?br />p?……p(j-k+1Q?p(j-k+2Q??..... p(j-1Q?p(j) || Q相配) || ||Q有待比较) p?p?…?..... p(k-1Q?p(k) ׃Q我们得到关p: 'p?p?p⑶?.p(k-1Q?= ' p(j-k+1Qp(j-k+2Q……p(j-1Q?br /> 不知道是从哪个课本上抄来的?其实q是不太明白最后一步?br /> ]]> 单的监视某个端口的连接数的Linux命o http://www.dentisthealthcenter.com/mstar/archive/2012/10/30/linux_shell_watch_connection.html黑灵 黑灵 Tue, 30 Oct 2012 01:38:00 GMT http://www.dentisthealthcenter.com/mstar/archive/2012/10/30/linux_shell_watch_connection.html http://www.dentisthealthcenter.com/mstar/comments/390432.html http://www.dentisthealthcenter.com/mstar/archive/2012/10/30/linux_shell_watch_connection.html#Feedback 0 http://www.dentisthealthcenter.com/mstar/comments/commentRss/390432.html http://www.dentisthealthcenter.com/mstar/services/trackbacks/390432.html # !/ bin / sh netstat - anp | grep :$ 1 | awk ' {print $5} ' | awk - F: ' {print $1} ' | sort | uniq - c
然后执行命o: watch -n 1 count_conn 8080 最后的参数是你要监视的端? ]]> 久久一级片