<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    少年阿賓

    那些青春的歲月

      BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
      500 Posts :: 0 Stories :: 135 Comments :: 0 Trackbacks

    #

    //研究了一下午,終于發(fā)現(xiàn)一個問題,寫這個代碼不是很難的,難的是找一個能代理的IP地址,實際網(wǎng)上的好多代碼都可以用滴,只是代理IP和Port有問題而已,廢話少說,直接上代碼:
    1、先說Get的代理(首先提供一個Servlet的Get的http服務(wù))

    package com.abin.lee.servlet;

    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.BufferedWriter;
    import java.io.IOException;
    import java.io.OutputStreamWriter;

    /**
     * Created with IntelliJ IDEA.
     * User: abin
     * Date: 13-4-18
     * Time: 上午8:39
     * To change this template use File | Settings | File Templates.
     */
    public class HttpClientGetProxyServlet extends HttpServlet {
        public void init(ServletConfig config) throws ServletException {
            super.init(config);
        }
        public void doGet(HttpServletRequest request,HttpServletResponse response)throws IOException {
            System.out.println("receive httpGet request");
            String userName=request.getParameter("userName");
            String passWord=request.getParameter("passWord");
            String localIp=request.getLocalAddr();
            String localName=request.getLocalName();
            int localPort=request.getLocalPort();
            int ServerPort=request.getServerPort();
            String leeHeader=request.getHeader("lee");
            System.out.println("userName="+userName+",passWord="+passWord+",localIp="+localIp+",localName="+localName+",localPort="+localPort);
            System.out.println("ServerPort="+ServerPort+",leeHeader="+leeHeader);
            String remoteIp=request.getRemoteAddr();
            String remoteHost=request.getRemoteHost();
            int remotePort=request.getRemotePort();
            System.out.println("remoteIp="+remoteIp+",remoteHost="+remoteHost+",remotePort="+remotePort);

            ServletOutputStream out=response.getOutputStream();
            BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(out));
            writer.write("success");
            writer.flush();
            writer.close();

        }
    }




    HttpGet代理測試類:

    package com.abin.lee.ssh.senior.proxy.httpclient;
    import org.apache.http.Header;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpHost;
    import org.apache.http.HttpResponse;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.conn.params.ConnRoutePNames;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.util.EntityUtils;
    import org.junit.Test;

    public class HttpClientGetProxyServletTest {
     public static final String HttpGetProxyUrl="http://localhost:8100/MyThread/HttpClientGetProxyServlet";
     @Test
        public  void testHttpClientPostProxyServlet()throws Exception {
            HttpHost proxy = new HttpHost("10.10.10.10", 1443, "http");
            DefaultHttpClient httpclient = new DefaultHttpClient();
            try {
                httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);

                HttpHost target = new HttpHost("localhost", 8100, "http");
                HttpGet request = new HttpGet(HttpGetProxyUrl+"?"+"userName=abin&passWord=varyall");
                request.setHeader("lee", "lee");
                System.out.println("executing request to " + target + " via " + proxy);
                HttpResponse rsp = httpclient.execute(target, request);
                HttpEntity entity = rsp.getEntity();

                System.out.println("----------------------------------------");
                System.out.println(rsp.getStatusLine());
                Header[] headers = rsp.getAllHeaders();
                for (int i = 0; i<headers.length; i++) {
                    System.out.println(headers[i]);
                }
                System.out.println("----------------------------------------");

                if (entity != null) {
                    System.out.println(EntityUtils.toString(entity));
                }

            } finally {
                // When HttpClient instance is no longer needed,
                // shut down the connection manager to ensure
                // immediate deallocation of all system resources
                httpclient.getConnectionManager().shutdown();
            }
        }
    }







    //正常測試代碼,非代理

    package com.abin.lee.ssh.senior.proxy.httpclient;

    import java.io.BufferedReader;
    import java.io.InputStreamReader;

    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.junit.Test;

    public class HttpClientGetServletTest {
     public static final String HttpGetUrl = "http://localhost:8100/MyThread/HttpClientGetProxyServlet";

     @Test
     public void HttpClientGetServlet() {
      HttpClient httpClient = new DefaultHttpClient();
      StringEntity reqEntity = null;
      HttpGet httpGet = null;
      try {
       HttpGet request = new HttpGet(HttpGetUrl+"?"+"userName=abin&passWord=varyall");
                request.setHeader("lee", "lee");
       // 目標地址
       System.out.println("請求: " + httpGet.getRequestLine());
       // 執(zhí)行
       HttpResponse response = httpClient.execute(httpGet);
       HttpEntity entity = response.getEntity();
       System.out.println("----------------------------------------");
       System.out.println(response.getStatusLine());
       if (entity != null) {
        System.out.println("Response content length: "
          + entity.getContentLength());
       }
       // 顯示結(jié)果
       BufferedReader reader = new BufferedReader(new InputStreamReader(
         entity.getContent(), "UTF-8"));
       String line = null;
       while ((line = reader.readLine()) != null) {
        System.out.println(line);
       }
      } catch (Exception e) {
       e.printStackTrace();
      } finally {
       if (!httpGet.isAborted()) {
        httpGet.abort();
       }
       httpClient.getConnectionManager().shutdown();
      }
     }
    }




    //servlet配置

       <servlet>
                 <servlet-name>HttpClientGetProxyServlet</servlet-name>
                 <servlet-class>com.abin.lee.servlet.HttpClientGetProxyServlet</servlet-class>
             </servlet>
             <servlet-mapping>
                 <servlet-name>HttpClientGetProxyServlet</servlet-name>
                 <url-pattern>/HttpClientGetProxyServlet</url-pattern>
             </servlet-mapping>






    我這里的IP和端口不一定能用喲,自己找能用的!!代碼是100%沒問題的,經(jīng)過生產(chǎn)環(huán)境測試的喲!!!
    posted @ 2013-04-18 17:50 abin 閱讀(1437) | 評論 (0)編輯 收藏

    //研究了一下午,終于發(fā)現(xiàn)一個問題,寫這個代碼不是很難的,難的是找一個能代理的IP地址,實際網(wǎng)上的好多代碼都可以用滴,只是代理IP和Port有問題而已,廢話少說,直接上代碼:
    1、先說Post的代理
    //HttpClientPostProxyServlet

    package com.abin.lee.servlet;

    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.BufferedWriter;
    import java.io.IOException;
    import java.io.OutputStreamWriter;

    /**
     * Created with IntelliJ IDEA.
     * User: abin
     * Date: 13-4-18
     * Time: 上午8:39
     * To change this template use File | Settings | File Templates.
     */
    public class HttpClientPostProxyServlet extends HttpServlet {
        public void init(ServletConfig config) throws ServletException {
            super.init(config);
        }
        public void doPost(HttpServletRequest request,HttpServletResponse response)throws IOException {
            System.out.println("receive httpPost request");
            String userName=request.getParameter("userName");
            String passWord=request.getParameter("passWord");
            String localIp=request.getLocalAddr();
            String localName=request.getLocalName();
            int localPort=request.getLocalPort();
            int serverPort=request.getServerPort();
            String leeHeader=request.getHeader("lee");
            System.out.println("userName="+userName+",passWord="+passWord+",localIp="+localIp+",localName="+localName+",localPort="+localPort);
            System.out.println("serverPort="+serverPort+",leeHeader="+leeHeader);
            String remoteIp=request.getRemoteAddr();
            String remoteHost=request.getRemoteHost();
            int remotePort=request.getRemotePort();
            String remoteUser=request.getRemoteUser();
            System.out.println("remoteIp="+remoteIp+",remoteHost="+remoteHost+",remotePort="+remotePort+",remoteUser="+remoteUser);

            ServletOutputStream out=response.getOutputStream();
            BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(out));
            writer.write("success");
            writer.flush();
            writer.close();

        }
    }




    Post代理測試類:
    //HttpClientPostProxyServletTest.java

    package com.abin.lee.ssh.senior.proxy.httpclient;
    import org.apache.http.Header;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpHost;
    import org.apache.http.HttpResponse;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.conn.params.ConnRoutePNames;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.util.EntityUtils;
    import org.junit.Test;

    public class HttpClientPostProxyServletTest {
     public static final String HttpPostProxyUrl="http://localhost:8100/MyThread/HttpClientPostProxyServlet";
     @Test
        public  void testHttpClientPostProxyServlet()throws Exception {
            HttpHost proxy = new HttpHost("10.10.10.10", 1443, "http");

            DefaultHttpClient httpclient = new DefaultHttpClient();
            try {
                httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);

                HttpHost target = new HttpHost("localhost", 8100, "http");
                HttpPost request = new HttpPost(HttpPostProxyUrl);
          StringEntity reqEntity = new StringEntity("userName=abin&passWord=varyall");  
          reqEntity.setContentType("application/x-www-form-urlencoded");  
          request.setEntity(reqEntity);  
          request.setHeader("lee", "lee");
                System.out.println("executing request to " + target + " via " + proxy);
                HttpResponse rsp = httpclient.execute(target, request);
                HttpEntity entity = rsp.getEntity();

                System.out.println("----------------------------------------");
                System.out.println(rsp.getStatusLine());
                Header[] headers = rsp.getAllHeaders();
                for (int i = 0; i<headers.length; i++) {
                    System.out.println(headers[i]);
                }
                System.out.println("----------------------------------------");

                if (entity != null) {
                    System.out.println(EntityUtils.toString(entity));
                }

            } finally {
                // When HttpClient instance is no longer needed,
                // shut down the connection manager to ensure
                // immediate deallocation of all system resources
                httpclient.getConnectionManager().shutdown();
            }
        }
    }




    //正常測試代碼,非代理

    package com.abin.lee.ssh.senior.proxy.httpclient;

    import java.io.BufferedReader;
    import java.io.InputStreamReader;

    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.junit.Test;

    public class HttpClientPostServletTest {
     public static final String HttpPostUrl="http://localhost:8100/MyThread/HttpClientPostProxyServlet";
     @Test
     public void testHttpClientPostServlet(){
       HttpClient httpClient = new DefaultHttpClient();
       HttpPost httpPost = new HttpPost(HttpPostUrl);
      try {
          // 目標地址  
           System.out.println("請求: " + httpPost.getRequestLine());  
          // 構(gòu)造最簡單的字符串數(shù)據(jù)  
           StringEntity reqEntity = new StringEntity("userName=abin&passWord=varyall");  
          // 設(shè)置類型  
           reqEntity.setContentType("application/x-www-form-urlencoded");  
          // 設(shè)置請求的數(shù)據(jù)  
           httpPost.setEntity(reqEntity);  
           httpPost.setHeader("lee", "lee");
          // 執(zhí)行  
           HttpResponse response = httpClient.execute(httpPost);  
           HttpEntity entity = response.getEntity();  
           System.out.println("----------------------------------------");  
           System.out.println(response.getStatusLine());  
          if (entity != null) {  
             System.out.println("Response content length: " + entity.getContentLength());  
           }  
          // 顯示結(jié)果  
           BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"));  
           String line = null;  
          while ((line = reader.readLine()) != null) {  
             System.out.println(line);  
           }  
      } catch (Exception e) {
       e.printStackTrace();
      }finally{
       if(!httpPost.isAborted()){
        httpPost.abort();
       }
       httpClient.getConnectionManager().shutdown();
      }
     }
    }



    //servlet配置
      <servlet>
                 <servlet-name>HttpClientPostProxyServlet</servlet-name>
                 <servlet-class>com.abin.lee.servlet.HttpClientPostProxyServlet</servlet-class>
             </servlet>
             <servlet-mapping>
                 <servlet-name>HttpClientPostProxyServlet</servlet-name>
                 <url-pattern>/HttpClientPostProxyServlet</url-pattern>
             </servlet-mapping>




    我這里的IP和端口不一定能用喲,自己找能用的!!代碼是100%沒問題的,經(jīng)過生產(chǎn)環(huán)境測試的喲!!!

    posted @ 2013-04-18 17:45 abin 閱讀(1176) | 評論 (1)編輯 收藏

         摘要: Introduction EasyMock (http://www.easymock.org/)使用Java的proxy機制即時為接口提供Mock Object (和擴展類的object)。因EasyMock獨特的期望記錄方式,大部分重構(gòu)不會印象Mock Object,故EasyMock很適合于TDD。 EasyMock的license為Apache 2.0 (details see...  閱讀全文
    posted @ 2013-04-10 22:06 abin 閱讀(357) | 評論 (0)編輯 收藏

    使用simple-spring-memcached統(tǒng)一緩存的使用

    如何在一個中型的Java應(yīng)用中使用Memcached緩存數(shù)據(jù)不是個簡單的問題。當某個緩存數(shù)據(jù)需要在多個系統(tǒng)間共享和失效時,必須要有統(tǒng)一的規(guī)劃才能保證不出錯。經(jīng)過各種實踐,目前系統(tǒng)在使用Memcached緩存數(shù)據(jù)全部采用Simple-Spring-Memcached框架來完成,并統(tǒng)一規(guī)劃各系統(tǒng)Spring和Cache key的配置。
    下面對在使用過程中需要注意的點做一個詳細說明:

    Cache整體規(guī)劃

    目前我們系統(tǒng)中有兩個不同的Memcached服務(wù)器:

    1. session memcached服務(wù)器:主要存儲用戶的session
    2. app memcached服務(wù)器: 主要用于緩存應(yīng)用數(shù)據(jù)

    由于應(yīng)用所有的緩存數(shù)據(jù)都放在app緩存上,為避免各應(yīng)用的緩存數(shù)據(jù)出現(xiàn)沖突,必須規(guī)劃好它們的命名空間。所幸Simple-Spring-Memcached支持namespace的概念,因此對各應(yīng)用的namespace前綴規(guī)定如下:

    應(yīng)用NAMESPACE前綴
    goodscentergoodscenter
    tradetrade
    uicuic

    這個namespace在生成key時,將放在最前面,稍后會有例子詳述。
    同一個應(yīng)用中存在許多需要緩存的對象,因此約定namespace前綴之后再加上緩存對象的類名。
    例子如下:

    應(yīng)用緩存對象完整的NAMESPACE最終生成的KEY
    tradeTcRate (id為42)trade:TcRatetrade:TcRate:12
    goodscenterGoodsDo(id為42)goodscenter:GoodsDogoodscenter:GoodsDo:12

    key的生成規(guī)則

    Simple-Spring-Memcached提供的針對單個對象的注解接口提供了兩種key生成方式,詳情見此文

    1. AssignCache類注解通過assignKey指定cache的key
    2. SingleCache類注解通過ParameterValueKeyProvider注解指定生成key的方法

    對于第一種只要求必須保證key不與其它的沖突,且namesapce符合規(guī)則。
    第二種時,約定緩存的數(shù)據(jù)對象必須實現(xiàn)有帶CacheKeyMethod的cacheKey方法,參考實現(xiàn)如下:

        @CacheKeyMethod     public String cacheKey() {         return this.getId();     }
    目前@CacheKeyMethod只支持返回String的方法,需要改造成可接受Long,Integer型的。當前必須有單獨的方法來作為緩存Key的生成器
    真實存放到Memcached的key的生成規(guī)則是:namespace:key。
    如goodscenter的id為42的domain對象GoodsDo,按上述方式生成的key為:goodscenter:GoodsDo:42

    spring配置說明

    關(guān)于Simple-Spring-Memcached具體XML配置如下:

    <beans xmlns="http://www.springframework.org/schema/beans"        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"        xmlns:context="http://www.springframework.org/schema/context"        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">      <import resource="classpath:simplesm-context.xml"/>      <aop:aspectj -autoproxy/>     <context:annotation -config/>      <bean name="appCache" class="com.google.code.ssm.CacheFactory">         <property name="cacheClientFactory">             <bean class="com.google.code.ssm.providers.xmemcached.MemcacheClientFactoryImpl"/>         </property>         <property name="addressProvider">             <bean class="com.google.code.ssm.config.DefaultAddressProvider">                 <!--memcached服務(wù)器ip:port 可以是多個,格式為: 127.0.0.1:11211,192.168.100.11:11211-->                 <property name="address" value="{memcached.server}"/>             </bean>         </property>         <property name="configuration">             <!-- memcached連接器的配置,具體的配置項參考這個類 -->             <bean class="com.google.code.ssm.providers.XMemcachedConfiguration">                 <!--是否使用一致性哈希-->                 <property name="consistentHashing" value="true"/>                 <!--連接池-->                 <property name="connectionPoolSize" value="10"/>                 <property name="optimizeGet" value="true"/>              </bean>         </property>         <property name="cacheName">             <!-- 該Memcached配置的Cache名稱 一個應(yīng)用中存在多個Memcached時,各個配置的cacheName必須不同。如果該值未設(shè),系統(tǒng)默認為default -->             <value>appCache</value>         </property>     </bean> </beans>

    Java代碼中使用說明

    a. 注解方式使用

    直接使用注解來處理緩存及失效非常簡單,下面是相應(yīng)的例子:
    讀取緩存:

    EventGoodsServiceClientImpl.java
        @Override     @ReadThroughSingleCache(namespace = "goodscenter:EventGoodsDo", expiration = 60)     @CacheName("appCache")     public EventGoodsDo queryEventGoodsDo(@ParameterValueKeyProvider(order = 0) long goodsId, @ParameterValueKeyProvider(order = 1) long eventId) {         return getRemoteServiceBean().queryEventGoodsDo(goodsId, eventId);     }

    更新緩存:

    EventGoodsDaoImpl.java
    @BridgeMethodMappings(value = {@BridgeMethodMapping(erasedParamTypes ={Object.class},targetParamTypes = {com.hqb360.promotion.dao.entity.EventGoods.class},methodName = "update")}) public class EventGoodsDaoImpl&lt;EventGoods&gt; extends BaseDaoImpl&lt;EventGoods&gt; implements EventGoodsDao&lt;EventGoods&gt; {      @Override     public DaoStatementName getDaoStatementName() {         return new DefaultDaoStatementName() {             public String getDomainName() {                 return "EventGoods";             }         };     }      @Override     @InvalidateSingleCache(namespace = "goodscenter:EventGoodsDo")     @CacheName("appCache")     public void update(@ParameterValueKeyProvider EventGoods obj) throws DataAccessException {         super.update(obj);     } }
    EventGoods.java
        @CacheKeyMethod     public String getCacheKey() {         return goodsId + CACHE_ID_SEPARATOR + eventId;     }      public static final String CACHE_ID_SEPARATOR = "/";
    上述代碼需要注意的點
    1. 多個方法參數(shù)都作為cacheKey時,ParameterValueKeyProvider必須指明其order值
    2. 多個方法參數(shù)作為cacheKey時,參數(shù)之間在 / 號分隔
    3. EventGoodsDaoImpl類中的update方法參數(shù)接收的是一個泛型對象,因此必須在該類上配置BridgeMethodMappings。具體配置見示例

    b. 以bean的方式使用Cache對象

    某些場景我們希望更便捷地自己手動來管理緩存數(shù)據(jù),此時需要使用Simple-Spring-Memcached配置中定義的bean。以上面的配置文件為例,使用方法如下
    bean的注入:

    @Autowired private Cache appCache;

    bean的使用:

    appCache.set(Constants.CACHE_KEY + members.getMemberId(), 3600,cacheValue);

    Posted in Java

     

    posted @ 2013-04-03 18:45 abin 閱讀(3744) | 評論 (0)編輯 收藏

    @CacheName指定緩存實例注解

    @CacheKeyMethod:緩存key生成注解

    ---------------------------------讀取-------------------------------------------

    @ReadThroughAssignCache(assignedKey = "SomePhatKey", namespace = "Echo", expiration = 3000): 讀取指定key緩存

    @ReadThroughSingleCache(namespace = SINGLE_NS, expiration = 0):讀取單個緩存

    @ReadThroughMultiCache(option = @ReadThroughMultiCacheOption(generateKeysFromResult = true)):讀取多個緩存

    @ReadThroughMultiCacheOption(generateKeysFromResult = true) 讀取多個緩存操作generateKeysFromResult 通過結(jié)果生成key

     

    ---------------------------------更新-------------------------------------------

    @UpdateAssignCache(assignedKey = "SomePhatKey", namespace = "Echo", expiration = 3000): 指定key更新緩存

    @UpdateSingleCache(namespace = SINGLE_NS, expiration = 2): 更新單個緩存(namespace 命名空間, expiration 失效時間單位秒)

    @UpdateMultiCache(namespace = "Bravo", expiration = 300): 更新多個緩存

     

    ---------------------------------失效-------------------------------------------

    @InvalidateAssignCache(assignedKey = "SomePhatKey", namespace = "Echo") : 指定key失效緩存

    @InvalidateSingleCache(namespace = SINGLE_NS):失效單個緩存

    @InvalidateMultiCache(namespace = "Delta") : 失效多個緩存

     

    ---------------------------------參數(shù)-------------------------------------------

    @ParameterDataUpdateContent標記方法的參數(shù)作為更新內(nèi)容。這個注解應(yīng)結(jié)合Update*Cache注解使用

    @ParameterValueKeyProvider: 標記將方法的參數(shù)做為計算緩存key.如果方法被注解的對象標記CacheKeyMethod的方法將會用來生成緩存key否則調(diào)用toString()生成

    @ParameterValueKeyProvider(order=0) 屬性表示如果多個參數(shù)做為key時需提供參數(shù)順序

    與@ParameterValueKeyProvider類似的注解有:

    {

      @ReturnValueKeyProvider返回值對象中計算key

    }

    ---------------------------------泛型處理-------------------------------------------

    @BridgeMethodMappings({ @BridgeMethodMapping(methodName = "updateUser", 

    erasedParamTypes = { Object.class }, targetParamTypes = { AppUser.class }) }): 泛型橋接注解

    methodName 指定方法

    erasedParamTypes 擦除對象類型

    targetParamTypes 目標轉(zhuǎn)換類型

     

     

    ---------------------------------計數(shù)器-------------------------------------------

    @InvalidateAssignCache  :在給的計算器上加1. 如果不存在則初始化為1

    @DecrementCounterInCache 在給的計數(shù)器上減1

     

    @ReadCounterFromCache  :讀取計數(shù)器

    @UpdateCounterFromCache 更新計數(shù)器

     

     

     

    Simple-Spring-Memcached代碼閱讀之BridgeMethod

     

    http://www.colorfuldays.org/program/java/bridgemethod%E7%9A%84%E4%BD%9C%E7%94%A8/

     

    http://www.colorfuldays.org/tag/ssm/   這個系列不錯

     

    b. 以bean的方式使用Cache對象

    某些場景我們希望更便捷地自己手動來管理緩存數(shù)據(jù),此時需要使用Simple-Spring-Memcached配置中定義的bean。以上面的配置文件為例,使用方法如下
    bean的注入:

    @Autowired private Cache appCache;

    bean的使用:

    appCache.set(Constants.CACHE_KEY + members.getMemberId(), 3600,cacheValue);
    posted @ 2013-04-03 18:43 abin 閱讀(1500) | 評論 (2)編輯 收藏

    主要是思維方式的不同: 

    顯然,RPC是以方法調(diào)用的方式描述WebSerivce的,也就是說,你要說清楚調(diào)用的那個方法,以及各個參數(shù)的名稱和值。要描述這些東東,SOAP消息就要有一個統(tǒng)一的規(guī)范,指出那一部分是方法名,哪個部分是參數(shù),哪個部分是返回值。換句話說,RPC方式調(diào)用的SOAP消息格式是有章可循的,固定的。(比如說,每個Parameter必須對應(yīng)一個Part,Part的name必須和參數(shù)名一致)。 

    而Document則是以文檔傳輸?shù)姆绞矫枋鯳ebService,只要你的SoapBody里面是一個可以用Schema描述的合法的Xml文檔就行了,對具體的格式?jīng)]有什么要求(Schema要在WSDL里面寫)。 

    可以看出,Document形式要更加靈活——尤其是需要傳輸特定格式的Xml文檔的時候,而RPC的Soap消息實際上也可以用Document形式模擬(只要Schema定義得當)。所以目前Document方式應(yīng)用更廣泛一些(也是.NET里面的缺省方式)。 

    對Namespace,我覺得兩者應(yīng)該沒有明顯的區(qū)別。主要是RPC通常與Encoding模式結(jié)合使用,這就要引用Soap的namespace了;而Document只要引用XmlSchema的Namespace定義類型就成了。

    posted @ 2013-04-02 15:26 abin 閱讀(561) | 評論 (0)編輯 收藏

    盡管是轉(zhuǎn)載的,但是原文中幾處錯誤或者不規(guī)范的表達,我已經(jīng)進行了修改。
     
    大部分 Web 服務(wù)都是圍繞著遠程過程調(diào)用而構(gòu)建的,而 WSDL 規(guī)范允許另外一種 Web 服務(wù)體系結(jié)構(gòu):文檔樣式( document style )。在該體系結(jié)構(gòu)中,整個文檔在服務(wù)客戶端和服務(wù)器之間進行交換。在本文中, James McCarthy 將向您解釋文檔樣式以及應(yīng)該何時使用它。
    Web 服務(wù)描述語言( Web Service Definition Language WDSL )規(guī)范中隱含著一個非常巧妙的轉(zhuǎn)換開關(guān),它可以將 Web 服務(wù)的 SOAP 綁定從遠程過程調(diào)用轉(zhuǎn)換成 pass-through 文檔。在 SOAP 協(xié)議綁定中的樣式屬性可以包含這兩個值中的一個: rpc document 。當屬性被設(shè)定為文檔樣式時,客戶端知道應(yīng)該使用 XML 模式而不是遠程過程調(diào)用約定。本文將提供對這個 WSDL 轉(zhuǎn)換開關(guān)的說明,描述它的好處,并將解釋應(yīng)該何時使用 pass-through 文檔。
    首先,讓我們簡要地談?wù)?/span> WSDL 的一些要點,來理解這個巧妙的轉(zhuǎn)換是如何發(fā)生的。 WSDL 是一項 XML 規(guī)范,它被用來描述Web服務(wù)以及對于到達端點(服務(wù))的協(xié)議相關(guān)的需求。 WSDL 用抽象術(shù)語來描述服務(wù);通過可擴展的綁定定義,它能夠為使用具體術(shù)語調(diào)用服務(wù)定義協(xié)議和數(shù)據(jù)格式規(guī)范。下面的語法是直接從 WSDL 規(guī)范中摘 錄出來的,展示了在綁定中所包含的可擴展性元素:

    <wsdl:definitions .... >
        <wsdl:binding name="nmtoken" type="qname"> *
            <-- extensibility element (1) --> *
            <wsdl:operation name="nmtoken"> *
               <-- extensibility element (2) --> *
               <wsdl:input name="nmtoken"? > ?
                   <-- extensibility element (3) -->
               </wsdl:input>
               <wsdl:output name="nmtoken"? > ?
                   <-- extensibility element (4) --> *
               </wsdl:output>
               <wsdl:fault name="nmtoken"> *
                   <-- extensibility element (5) --> *
               </wsdl:fault>
            </wsdl:operation>
        </wsdl:binding>
    </wsdl:definitions>

     
    WSDL 規(guī)范通常描述三種綁定擴展: HTTP GET/POST MIME 以及 SOAP version 1.1 HTTP GET/POST MIME 中定義的綁定擴展用來定義與標準的 Web 應(yīng)用程序進行通信的需
    求,這些應(yīng)用程序可能返回(也可能不返回) XML 文檔。在發(fā)送或返回 XML 文檔時, HTTP GET/POST 綁定的擴展是隱式的文檔樣式。
    SOAP 綁定擴展用來定義支持 SOAP 信封協(xié)議的服務(wù)。 SOAP 信封是一種簡單模式,它設(shè)計成能包含 XML 消息,提供特定于應(yīng)用程序的消息頭和消息體。 SOAP 綁定的擴展使 WSDL 文檔能夠聲明 SOAP 消息的需求,這樣應(yīng)用程序就能夠與服務(wù)正確通信。 SOAP 擴展允許將 SOAP 消息的樣式聲明為文檔或 RPC 。如果在 soap:binding 元素中聲明了樣式屬性,那么該樣式將成為所有沒有顯式聲明的樣式屬性的 soap:operation 元素的缺省值。如果在 soap:binding 元素中沒有聲明樣式屬性,那么缺省的樣式就是文檔。下面是文檔樣式的顯式聲明:

    <soap:binding style="document" transport="uri">

     
    不管 soap:binding 元素中的聲明如何, soap:operation 元素可以覆蓋每個操作的聲明,就像這樣的:

     
    <soap:operation soapAction="uri" style="document">

     
    在聲明了文檔樣式的 SOAP 消息中,原始( as-is )或編碼( encoded )的消息被直接放置在 SOAP 信封的體部。
    如果樣式聲明為 RPC ,消息就封裝在包裝器元素中,同時帶有從操作名屬性中提取的的元素的名稱以及從操作名稱空間屬性中提取的名稱空間。
    勿庸置疑,使用 XML 調(diào)用跨平臺的遠程過程調(diào)用的能力是非常有用的,它是使用 Web 服務(wù)的非常有說服力的理由。但是如果 Web 服務(wù)僅僅局限于 RPC 消息傳遞,這項技術(shù)的影響將是有限的。幸運的是,開發(fā)人員可以選擇是使用 RPC 還是文檔樣式的消息傳遞,并且能夠使用適合的技術(shù)來完成他們面臨的任務(wù)。
    XML 規(guī)范開發(fā)用來使通常鎖定于專有格式的常規(guī)數(shù)據(jù)可以以一種人易讀的、自描述的、自驗證的開放格式來描述。當 Web 服務(wù)使用文檔消息傳遞時,它可以利用 XML 的全部能力來描述和驗證高級業(yè)務(wù)文檔。當服務(wù)使用 RPC 消息格式化時, XML 描述方法以及為方法調(diào)用編碼的參數(shù),但是卻不能用來執(zhí)行高級業(yè)務(wù)規(guī)則。為了執(zhí)行這些規(guī)則, RPC 消息必須包含 XML 文檔作為字符串參數(shù)并且在被調(diào)用的方法中隱藏驗證。出于這個原因, XML 的某些好處就喪失了,或者至少是被隱藏在后臺應(yīng)用程序里了。
    使用文檔消息傳遞的另外一個原因在于,遠程過程調(diào)用必須是相對靜態(tài)的,并且對接口的任何變化都將破壞服務(wù)和應(yīng)用程序之間的契約。如果服務(wù)是廣泛分布的,那么很可能大量的應(yīng)用程序已經(jīng)從它的 WSDL 文檔中產(chǎn)生了存根代碼。改變 WSDL 將會導致所有依賴于特定方法簽名的應(yīng)用程序被破壞,而且許多支持行產(chǎn)生問題。好的設(shè)計要求 RPC 消息服務(wù)的方法簽名不應(yīng)該改變。使用文檔消息傳遞,規(guī)則更嚴格,并且可以使 XML 模式得到顯著增強和改變,同時又不會破壞調(diào)用應(yīng)用程序。
    當業(yè)務(wù)使用基于 Web 的應(yīng)用程序通過 Internet 交換信息時,應(yīng)用程序應(yīng)該能夠使用有保證的交付機制來提高它的可靠性、可伸縮性和性能。為了達到這個目的,應(yīng)用程序通常將使用異步消息隊列。由于文檔消息通常是自包含的,所以它更適合于異步處理,并且可以直接放到隊列中。之所以說應(yīng)用程序的可靠性得到了提高,是因為即使目標應(yīng)用程序當前不是活動的,消息隊列也可以保證消息的交付;之所以說性能得到了提高,是因為 Web 應(yīng)用程序只是把文檔發(fā)送到隊列中,然后便可以自由地執(zhí)行其他的任務(wù);之所以說可擴展性得到了提高,是因為文檔被下傳到一個或多個應(yīng)用程序的實例以進行處理。
    業(yè)務(wù)文檔的設(shè)計通常很好地適于面向?qū)ο蟮捏w系結(jié)構(gòu)。結(jié)果,兩個應(yīng)用程序可以設(shè)計成通過使用 XML 交換對象的狀態(tài)。與對象序列化相比,在對象交換中,交換的每個端點都可以自由地設(shè)計它認為合適的對象,只要交換符合達成協(xié)議的 XML 文件格式即可。不使用對象序列化的一個原因是為了支持對象在客戶端和服務(wù)器端的實現(xiàn)。許多現(xiàn)有的特定于行業(yè)的 XML 模式被設(shè)計成客戶端 / 服務(wù)器體系結(jié)構(gòu),在這種體系結(jié)構(gòu)中,在客戶端上完成的處理與預(yù)定在服務(wù)器上完成的處理是分離的。通常的情況是,客戶端僅僅以服務(wù)器要求的特定文檔格式請求或保存信息。當然,這種類型的交換也能用 RPC 消息完成,但是這種消息的編碼方式限制了每個端點上的對象的設(shè)計。在文檔樣式中就不會出現(xiàn)這些限制問題。
    什么時候應(yīng)該使用文檔樣式呢?簡單地說:只要沒有連接到已存在的遠程過程調(diào)用,任何時候都可以使用文檔方式。使用文檔方式比起通常花費額外的工作來連接服務(wù),好處要大得多。不過需要提醒的是:一般來說,構(gòu)建一個使用文檔消息傳遞的服務(wù)的工作量要比構(gòu)建一個 RPC 消息服務(wù)所需的工作量大。這些額外的工作通常包括 XML 模式的設(shè)計或?qū)σ汛嬖诘哪J降闹С帧⒁约皬奈臋n中提取相關(guān)的信息。模式設(shè)計是重要的,因為 XML 解析器使用這個模式來驗證文檔,支持預(yù)定的業(yè)務(wù)規(guī)則。服務(wù)需要進行額外的工作來從文檔中提取用于處理請求的相關(guān)信息。相比之下, RPC 消息只需要設(shè)計方法的接口,通過方法的接口, RPC 消息就可以自動地編組和解組參數(shù)。
    當您決定發(fā)布一項服務(wù)時,您可能應(yīng)該考慮下列問題。我將在下面的部分中分析您的答案的結(jié)果。
    • 這項服務(wù)是連接到已存在的過程調(diào)用,并且這個過程調(diào)用是無狀態(tài)的嗎?
    • 這項服務(wù)是僅在您的組織內(nèi)部使用,還是也可以被外部用戶所使用?
    • 參數(shù)之一僅僅是 XML 文檔規(guī)范嗎?
    • 這項服務(wù)需要請求 / 響應(yīng)體系結(jié)構(gòu)嗎?
    • 參數(shù)表示了可以從用于驗證的 XML 文檔模式受益的復雜結(jié)構(gòu)嗎?
    • 所有需要進行交換的信息都能夠合理地存放在內(nèi)存中嗎?
     如果必須以特定的順序調(diào)用多個過程來維護應(yīng)用程序狀態(tài),您應(yīng)該考慮在您的服務(wù)中使用文檔體系結(jié)構(gòu)。如果需要多個過程調(diào)用,那么過程就不是無狀態(tài)的,并且服務(wù)必須維護應(yīng)用程序狀態(tài)。在 Web 服務(wù)中維護狀態(tài)可能是困難的;在遠程過程調(diào)用的情況下,很少有客戶端平臺會產(chǎn)生能夠支持狀態(tài)信息的存根代碼。一個可能的解決方案是使用文檔體系結(jié)構(gòu),并在文檔內(nèi)部傳送整個事務(wù)的內(nèi)容。在這種情況下,服務(wù)將執(zhí)行調(diào)用,以確保服務(wù)內(nèi)部保持正確的順序,并且狀態(tài)信息的維護不超出單個事務(wù)的范圍。如果仍然需要狀態(tài)信息,可以將狀態(tài)信息記錄在最終得到的文檔中,客戶端應(yīng)用程序也可以維護一個用于服務(wù)識別它的狀態(tài)的令牌。
    如果一個應(yīng)用程序被發(fā)布到組織以外,發(fā)布者就很難控制誰正依賴于這個服務(wù),以及如果做出任何改動后果會怎樣。在這種情況下,使用文檔消息傳遞和支持像 ebXML 這樣的通用交換協(xié)議可能更加有利。通用交換協(xié)議正發(fā)展成能改善外部交換的管理,因此新的貿(mào)易合作伙伴協(xié)定就可以快速地部署。同樣,如果您的服務(wù)不需要請求 / 響應(yīng)體系結(jié)構(gòu),那么通用交換協(xié)議就可以更好地設(shè)計來處理認證、可靠消息交付以及異步請求 / 響應(yīng)。
    如果您的服務(wù)正使用字符串參數(shù)來傳遞或返回 XML 文檔,或者它的參數(shù)之一是一個具有復雜結(jié)構(gòu)且需要自定義處理的對象,那么文檔消息傳遞就可能是較好的選擇。將參數(shù)的真實含義隱藏在字符串里經(jīng)常會導致帶有無效參數(shù)的有效調(diào)用。如果服務(wù)發(fā)布了 XML 文檔模式,那么在調(diào)用服務(wù)之前根據(jù)這個模式進行驗證就會更加容易。復雜結(jié)構(gòu)經(jīng)常用來傳遞組成完整事務(wù)的數(shù)百條信息。在處理復雜的結(jié)構(gòu)時,遠程過程服務(wù)可能不得不處理自定義的編組代碼,同時應(yīng)用程序仍然負責仔細地驗證結(jié)構(gòu)的每個元素。如果使用文檔消息傳遞,那么應(yīng)用程序程序員就可以使用 XML 模式來將驗證下傳到文檔設(shè)計器,并且不需要自定義的編組代碼。
        擇使用文檔樣式的消息傳遞還是 RPC 樣式的消息傳遞時,需要考慮的最后一個因素是需要處理的信息量大小。由于采用 RPC 樣式的消息傳遞來編組參數(shù)的大部分(如果不是全部的話)實現(xiàn)都是在內(nèi)存中執(zhí)行這項操作,所以內(nèi)存約束可能會使得 RPC 消息傳遞行不通。許多文檔消息傳遞服務(wù)能夠選擇是用 DOM 還是用 SAX 來處理文檔,因而能夠最小化內(nèi)存中的處理。這對于 Web 服務(wù)尤為關(guān)鍵,因為它可能需要處理成千上萬的請求,而且其中許多是同時發(fā)生的。
    在您設(shè)計下一個 Web 服務(wù)時,您需要考慮當前的 WSDL 規(guī)范為您提供的所有選擇。在開始創(chuàng)建過程性的接口之前,考慮好將如何使用服務(wù),誰將使用它,以及需要交換的數(shù)據(jù)的類型和數(shù)量。設(shè)計開發(fā)文檔樣式的 Web 服務(wù)可能需要稍多一些的工作量,但是在很多情況下,這些額外的工作量將會換取更高的信息質(zhì)量和更可靠的交換性能。
    posted @ 2013-04-02 15:02 abin 閱讀(1393) | 評論 (0)編輯 收藏

    TCP/IP:
    數(shù)據(jù)鏈路層:ARP,RARP
    網(wǎng)絡(luò)層: IP,ICMP,IGMP
    傳輸層:TCP ,UDP,UGP
    應(yīng)用層:Telnet,FTP,SMTP,SNMP.

    OSI:
    物理層:EIA/TIA-232, EIA/TIA-499, V.35, V.24, RJ45, Ethernet, 802.3, 802.5, FDDI, NRZI, NRZ, B8ZS
    數(shù)據(jù)鏈路層:Frame Relay, HDLC, PPP, IEEE 802.3/802.2, FDDI, ATM,  IEEE 802.5/802.2
    網(wǎng)絡(luò)層:IP,IPX,AppleTalk DDP
    傳輸層:TCP,UDP,SPX
    會話層:RPC,SQL,NFS,NetBIOS,names,AppleTalk,ASP,DECnet,SCP
    表示層:TIFF,GIF,JPEG,PICT,ASCII,EBCDIC,encryption,MPEG,MIDI,HTML
    應(yīng)用層:FTP,WWW,Telnet,NFS,SMTP,Gateway,SNMP

    應(yīng)用層
    1.主要功能 :用戶接口、應(yīng)用程序
    application 2.典型設(shè)備:網(wǎng)關(guān)
    3.典型協(xié)議、標準和應(yīng)用:TELNET, FTP, HTTP

    表示層
    1.主要功能 :數(shù)據(jù)的表示、壓縮和加密
    presentation2.典型設(shè)備:網(wǎng)關(guān)
    3.典型協(xié)議、標準和應(yīng)用:ASCLL、PICT、TIFF、JPEG、 MIDI、MPEG

    會話層
    1.主要功能 :會話的建立和結(jié)束
    session2.典型設(shè)備:網(wǎng)關(guān)
    3.典型協(xié)議、標準和應(yīng)用:RPC、SQL、NFS 、X WINDOWS、ASP


    傳輸層
    1.主要功能 :端到端控制
    transport 2.典型設(shè)備:網(wǎng)關(guān)
    3.典型協(xié)議、標準和應(yīng)用:TCP、UDP、SPX

    網(wǎng)絡(luò)層
    1.主要功能 :路由,尋址
    network2.典型設(shè)備:路由器
    3.典型協(xié)議、標準和應(yīng)用:IP、IPX、APPLETALK、ICMP

    數(shù)據(jù)鏈路層
    1.主要功能 :保證誤差錯的數(shù)據(jù)鏈路
    data link 2.典型設(shè)備:交換機、網(wǎng)橋、網(wǎng)卡
    3.典型協(xié)議、標準和應(yīng)用:802.2、802.3ATM、HDLC、FRAME RELAY

    物理層
    1.主要功能 :傳輸比特流
    physical2.典型設(shè)備:集線器、中繼器
    3.典型協(xié)議、標準和應(yīng)用:V.35、EIA/TIA-232

    從下到上,物理層最低的!!!!應(yīng)用層最高。

    什么是TCP/IP協(xié)議,劃為幾層,各有什么功能?
    TCP/IP協(xié)議族包含了很多功能各異的子協(xié)議。為此我們也利用上文所述的分層的方式來剖析它的結(jié)構(gòu)。TCP/IP層次模型共分為四層:應(yīng)用層、傳輸層、網(wǎng)絡(luò)層、數(shù)據(jù)鏈路層。

    TCP/IP網(wǎng)絡(luò)協(xié)議
    TCP/IP(Transmission Control Protocol/Internet Protocol,傳輸控制協(xié)議/網(wǎng)間網(wǎng)協(xié)議)是目前世界上應(yīng)用最為廣泛的協(xié)議,它的流行與Internet的迅猛發(fā)展密切相關(guān)—TCP/IP最初是為互聯(lián)網(wǎng)的原型ARPANET所設(shè)計的,目的是提供一整套方便實用、能應(yīng)用于多種網(wǎng)絡(luò)上的協(xié)議,事實證明TCP/IP做到了這一點,它使網(wǎng)絡(luò)互聯(lián)變得容易起來,并且使越來越多的網(wǎng)絡(luò)加入其中,成為Internet的事實標準。

    * 應(yīng)用層—應(yīng)用層是所有用戶所面向的應(yīng)用程序的統(tǒng)稱。ICP/IP協(xié)議族在這一層面有著很多協(xié)議來支持不同的應(yīng)用,許多大家所熟悉的基于Internet的應(yīng)用的實現(xiàn)就離不開這些協(xié)議。如我們進行萬維網(wǎng)(WWW)訪問用到了HTTP協(xié)議、文件傳輸用FTP協(xié)議、電子郵件發(fā)送用SMTP、域名的解析用DNS協(xié)議、遠程登錄用Telnet協(xié)議等等,都是屬于TCP/IP應(yīng)用層的;就用戶而言,看到的是由一個個軟件所構(gòu)筑的大多為圖形化的操作界面,而實際后臺運行的便是上述協(xié)議。

    * 傳輸層—這一層的的功能主要是提供應(yīng)用程序間的通信,TCP/IP協(xié)議族在這一層的協(xié)議有TCP和UDP。

    * 網(wǎng)絡(luò)層—是TCP/IP協(xié)議族中非常關(guān)鍵的一層,主要定義了IP地址格式,從而能夠使得不同應(yīng)用類型的數(shù)據(jù)在Internet上通暢地傳輸,IP協(xié)議就是一個網(wǎng)絡(luò)層協(xié)議。

    * 網(wǎng)絡(luò)接口層—這是TCP/IP軟件的最低層,負責接收IP數(shù)據(jù)包并通過網(wǎng)絡(luò)發(fā)送之,或者從網(wǎng)絡(luò)上接收物理幀,抽出IP數(shù)據(jù)報,交給IP層。

    1.TCP/UDP協(xié)議
    TCP (Transmission Control Protocol)和UDP(User Datagram Protocol)協(xié)議屬于傳輸層協(xié)議。其中TCP提供IP環(huán)境下的數(shù)據(jù)可靠傳輸,它提供的服務(wù)包括數(shù)據(jù)流傳送、可靠性、有效流控、全雙工操作和多路復用。通過面向連接、端到端和可靠的數(shù)據(jù)包發(fā)送。通俗說,它是事先為所發(fā)送的數(shù)據(jù)開辟出連接好的通道,然后再進行數(shù)據(jù)發(fā)送;而UDP則不為IP提供可靠性、流控或差錯恢復功能。一般來說,TCP對應(yīng)的是可靠性要求高的應(yīng)用,而UDP對應(yīng)的則是可靠性要求低、傳輸經(jīng)濟的應(yīng)用。TCP支持的應(yīng)用協(xié)議主要有:Telnet、FTP、SMTP等;UDP支持的應(yīng)用層協(xié)議主要有:NFS(網(wǎng)絡(luò)文件系統(tǒng))、SNMP(簡單網(wǎng)絡(luò)管理協(xié)議)、DNS(主域名稱系統(tǒng))、TFTP(通用文件傳輸協(xié)議)等。

    IP協(xié)議的定義、IP地址的分類及特點

    什么是IP協(xié)議,IP地址如何表示,分為幾類,各有什么特點?
    為了便于尋址和層次化地構(gòu)造網(wǎng)絡(luò),IP地址被分為A、B、C、D、E五類,商業(yè)應(yīng)用中只用到A、B、C三類。

    IP協(xié)議(Internet Protocol)又稱互聯(lián)網(wǎng)協(xié)議,是支持網(wǎng)間互連的數(shù)據(jù)報協(xié)議,它與TCP協(xié)議(傳輸控制協(xié)議)一起構(gòu)成了TCP/IP協(xié)議族的核心。它提供網(wǎng)間連接的完善功能, 包括IP數(shù)據(jù)報規(guī)定互連網(wǎng)絡(luò)范圍內(nèi)的IP地址格式。

    Internet 上,為了實現(xiàn)連接到互聯(lián)網(wǎng)上的結(jié)點之間的通信,必須為每個結(jié)點(入網(wǎng)的計算機)分配一個地址,并且應(yīng)當保證這個地址是全網(wǎng)唯一的,這便是IP地址。

    目前的IP地址(IPv4:IP第4版本)由32個二進制位表示,每8位二進制數(shù)為一個整數(shù),中間由小數(shù)點間隔,如159.226.41.98,整個IP地址空間有4組8位二進制數(shù),由表示主機所在的網(wǎng)絡(luò)的地址(類似部隊的編號)以及主機在該網(wǎng)絡(luò)中的標識(如同士兵在該部隊的編號)共同組成。

    為了便于尋址和層次化的構(gòu)造網(wǎng)絡(luò),IP地址被分為A、B、C、D、E五類,商業(yè)應(yīng)用中只用到A、B、C三類。

    * A類地址:A類地址的網(wǎng)絡(luò)標識由第一組8位二進制數(shù)表示,網(wǎng)絡(luò)中的主機標識占3組8位二進制數(shù),A類地址的特點是網(wǎng)絡(luò)標識的第一位二進制數(shù)取值必須為 “0”。不難算出,A類地址允許有126個網(wǎng)段,每個網(wǎng)絡(luò)大約允許有1670萬臺主機,通常分配給擁有大量主機的網(wǎng)絡(luò)(如主干網(wǎng))。

    * B類地址:B類地址的網(wǎng)絡(luò)標識由前兩組8位二進制數(shù)表示,網(wǎng)絡(luò)中的主機標識占兩組8位二進制數(shù),B類地址的特點是網(wǎng)絡(luò)標識的前兩位二進制數(shù)取值必須為“10”。B類地址允許有16384個網(wǎng)段,每個網(wǎng)絡(luò)允許有65533臺主機,適用于結(jié)點比較多的網(wǎng)絡(luò)(如區(qū)域網(wǎng))。

    * C類地址:C類地址的網(wǎng)絡(luò)標識由前3組8位二進制數(shù)表示,網(wǎng)絡(luò)中主機標識占1組8位二進制數(shù),C類地址的特點是網(wǎng)絡(luò)標識的前3位二進制數(shù)取值必須為“110”。具有C類地址的網(wǎng)絡(luò)允許有254臺主機,適用于結(jié)點比較少的網(wǎng)絡(luò)(如校園網(wǎng))。

    為了便于記憶,通常習慣采用4個十進制數(shù)來表示一個IP地址,十進制數(shù)之間采用句點“.”予以分隔。這種IP地址的表示方法也被稱為點分十進制法。如以這種方式表示,A類網(wǎng)絡(luò)的IP地址范圍為1.0.0.1-127.255.255.254;B類網(wǎng)絡(luò)的IP地址范圍為:128.1.0.1-191.255.255.254;C類網(wǎng)絡(luò)的IP地址范圍為:192.0.1.1-223.255.255.254。

    由于網(wǎng)絡(luò)地址緊張、主機地址相對過剩,采取子網(wǎng)掩碼的方式來指定網(wǎng)段號。

    TCP/IP協(xié)議與低層的數(shù)據(jù)鏈路層和物理層無關(guān),這也是TCP/IP的重要特點。正因為如此 ,它能廣泛地支持由低兩層協(xié)議構(gòu)成的物理網(wǎng)絡(luò)結(jié)構(gòu)。目前已使用TCP/IP連接成洲際網(wǎng)、全國網(wǎng)與跨地區(qū)網(wǎng)。

    OSP與TCP/IP的參考層次圖:

     

    OSI七層協(xié)議和TCP/IP四層協(xié)議之比較

     

    OSP與TCP/IP的比較:

    分層結(jié)構(gòu)
    OSI參考模型與TCP/IP協(xié)議都采用了分層結(jié)構(gòu),都是基于獨立的協(xié)議棧的概念。OSI參考模型有7層,而TCP/IP協(xié)議只有4層,即TCP/IP協(xié)議沒有了表示層和會話層,并且把數(shù)據(jù)鏈路層和物理層合并為網(wǎng)絡(luò)接口層。不過,二者的分層之間有一定的對應(yīng)關(guān)系

    標準的特色
    OSI參考模型的標準最早是由ISO和CCITT(ITU的前身)制定的,有濃厚的通信背景,因此也打上了深厚的通信系統(tǒng)的特色,比如對服務(wù)質(zhì)量(QoS)、差錯率的保證,只考慮了面向連接的服務(wù)。并且是先定義一套功能完整的構(gòu)架,再根據(jù)該構(gòu)架來發(fā)展相應(yīng)的協(xié)議與系統(tǒng)。

    TCP/IP協(xié)議產(chǎn)生于對Internet網(wǎng)絡(luò)的研究與實踐中,是應(yīng)實際需求而產(chǎn)生的,再由IAB、IETF等組織標準化,而并不是之前定義一個嚴謹?shù)目蚣堋6襎CP/IP最早是在UNIX系統(tǒng)中實現(xiàn)的,考慮了計算機網(wǎng)絡(luò)的特點,比較適合計算機實現(xiàn)和使用。

    連接服務(wù)
    OSI的網(wǎng)絡(luò)層基本與TCP/IP的網(wǎng)際層對應(yīng),二者的功能基本相似,但是尋址方式有較大的區(qū)別。

    OSI的地址空間為不固定的可變長,由選定的地址命名方式?jīng)Q定,最長可達160byte,可以容納非常大的網(wǎng)絡(luò),因而具有較大的成長空間。根據(jù)OSI的規(guī)定,網(wǎng)絡(luò)上每個系統(tǒng)至多可以有256個通信地址。

    TCP/IP網(wǎng)絡(luò)的地址空間為固定的4byte(在目前常用的IPV4中是這樣,在IPV6中將擴展到16byte)。網(wǎng)絡(luò)上的每一個系統(tǒng)至少有一個唯一的地址與之對應(yīng)。

    傳輸服務(wù)
    OSI與TCP/IP的傳輸層都對不同的業(yè)務(wù)采取不同的傳輸策略。OSI定義了五個不同層次的服務(wù):TP1,TP2,TP3,TP4,TP5。TCP/IP定義了TCP和UPD兩種協(xié)議,分別具有面向連接和面向無連接的性質(zhì)。其中TCP與OSI中的TP4,UDP與OSI中的TP0在構(gòu)架和功能上大體相同,只是內(nèi)部細節(jié)有一些差異。

    應(yīng)用范圍
    OSI由于體系比較復雜,而且設(shè)計先于實現(xiàn),有許多設(shè)計過于理想,不太方便計算機軟件實現(xiàn),因而完全實現(xiàn)OSI參考模型的系統(tǒng)并不多,應(yīng)用的范圍有限。而TCP/IP協(xié)議最早在計算機系統(tǒng)中實現(xiàn),在UNIX、Windows平臺中都有穩(wěn)定的實現(xiàn),并且提供了簡單方便的編程接口(API),可以在其上開發(fā)出豐富的應(yīng)用程序,因此得到了廣泛的應(yīng)用。TCP/IP協(xié)議已成為目前網(wǎng)際互聯(lián)事實上的國際標準和工業(yè)標準。

    posted @ 2013-03-28 21:26 abin 閱讀(836) | 評論 (0)編輯 收藏

     數(shù)據(jù)庫連接池在初始化的時候會創(chuàng)建initialSize個連接,當有數(shù)據(jù)庫操作時,會從池中取出一個連接。如果當前池中正在使用的連接數(shù)等于maxActive,則會等待一段時間,等待其他操作釋放掉某一個連接,如果這個等待時間超過了maxWait,則會報錯;如果當前正在使用的連接數(shù)沒有達到maxActive,則判斷當前是否空閑連接,如果有則直接使用空閑連接,如果沒有則新建立一個連接。在連接使用完畢后,不是將其物理連接關(guān)閉,而是將其放入池中等待其他操作復用。
      對于一個數(shù)據(jù)庫連接池,一般包括一下屬性。
      
      
      名稱   說明   備注
    minIdle 最小活躍數(shù) 可以允許的空閑連接數(shù)目
    maxActive 最大連接數(shù) 相當于池的大小
    initialSize 初始化連接大小
    maxWait 獲取連接的最大等待時間
    timeBetweenEvictionRunsMillis 空閑連接的最大生存時間 指定空閑連接在空閑多長時間后,關(guān)閉其物理連接
    testWhileIdle 是否在空閑時檢測連接可用性 由于網(wǎng)絡(luò)或者數(shù)據(jù)庫配置的原因(比如mysql連接的8小時限制),開啟這個開關(guān)可以定期檢測連接的可用性
    posted @ 2013-03-27 10:32 abin 閱讀(567) | 評論 (0)編輯 收藏


     

    鎖:

    1. 內(nèi)置鎖 (監(jiān)視器鎖): 每個java對象都可以做一個實現(xiàn)同步的鎖,這些鎖被成為內(nèi)置鎖. 獲得鎖的唯一途徑就是進入有這個鎖保護的代碼塊或方法
    2. 重入鎖: 由于內(nèi)置鎖是可重入的,因此如果某個線程試圖獲得一個以已經(jīng)由他自己持有的鎖, 那么這個請求就會成功.重入意味著獲取鎖的操作粒度是"線程",而不是"調(diào)用"

    volatile 使用條件(必須同時滿足所有條件):

    1. 對變量的寫入操作不依賴變量的當前值,或者你能確保只有單個線程更新變量的值
    2. 該變量不會與其他狀態(tài)變量一起納入不變性條件中
    3. 在訪問變量時間不需要加鎖


     


     

    高并發(fā)術(shù)語



    術(shù)語

    英文單詞

    描述

    比較并交換

    Compare and Swap

    CAS操作需要輸入兩個數(shù)值,一個舊值(期望操作前的值)和一個新值,在操作期間先比較下舊值有沒有發(fā)生變化,如果沒有發(fā)生變化,才交換成新值,發(fā)生了變化則不交換

    CPU流水線

    CPU pipeline

    CPU流水線的工作方式就象工業(yè)生產(chǎn)上的裝配流水線,在CPU中由5~6個不同功能的電路單元組成一條指令處理流水線,然后將一條X86指令分成5~6步后再由這些電路單元分別執(zhí)行,這樣就能實現(xiàn)在一個CPU時鐘周期完成一條指令,因此提高CPU的運算速度

    內(nèi)存順序沖突

    Memory order violation

    內(nèi)存順序沖突一般是由假共享引起,假共享是指多個CPU同時修改同一個緩存行的不同部分而引起其中一個CPU的操作無效,當出現(xiàn)這個內(nèi)存順序沖突時,CPU必須清空流水線

    共享變量


    在多個線程之間能夠被共享的變量被稱為共享變量。共享變量包括所有的實例變量,靜態(tài)變量和數(shù)組元素。他們都被存放在堆內(nèi)存中,Volatile只作用于共享變量。

    內(nèi)存屏障

    Memory Barriers

    是一組處理器指令,用于實現(xiàn)對內(nèi)存操作的順序限制。

    緩沖行

    Cache line

    緩存中可以分配的最小存儲單位。處理器填寫緩存線時會加載整個緩存線,需要使用多個主內(nèi)存讀周期。

    原子操作

    Atomic operations

    不可中斷的一個或一系列操作。

    緩存行填充

    cache line fill

    當處理器識別到從內(nèi)存中讀取操作數(shù)是可緩存的,處理器讀取整個緩存行到適當?shù)木彺妫↙1,L2,L3的或所有)

    緩存命中

    cache hit

    如果進行高速緩存行填充操作的內(nèi)存位置仍然是下次處理器訪問的地址時,處理器從緩存中讀取操作數(shù),而不是從內(nèi)存。

    寫命中

    write hit

    當處理器將操作數(shù)寫回到一個內(nèi)存緩存的區(qū)域時,它首先會檢查這個緩存的內(nèi)存地址是否在緩存行中,如果存在一個有效的緩存行,則處理器將這個操作數(shù)寫回到緩存,而不是寫回到內(nèi)存,這個操作被稱為寫命中。



     

    synchronized

    volatile

    concurrent 

    在并發(fā)編程中很常用的實用工具類。此包包括了幾個小的、已標準化的可擴展框架,以及一些提供有用功能的類,沒有這些類,這些功能會很難實現(xiàn)或?qū)崿F(xiàn)起來冗長乏味。下面簡要描述主要的組件。另請參閱 locks 和 atomic 包。

    執(zhí)行程序

    接口。Executor 是一個簡單的標準化接口,用于定義類似于線程的自定義子系統(tǒng),包括線程池、異步 IO 和輕量級任務(wù)框架。根據(jù)所使用的具體 Executor 類的不同,可能在新創(chuàng)建的線程中,現(xiàn)有的任務(wù)執(zhí)行線程中,或者調(diào)用 execute() 的線程中執(zhí)行任務(wù),并且可能順序或并發(fā)執(zhí)行。ExecutorService 提供了多個完整的異步任務(wù)執(zhí)行框架。ExecutorService 管理任務(wù)的排隊和安排,并允許受控制的關(guān)閉。ScheduledExecutorService 子接口及相關(guān)的接口添加了對延遲的和定期任務(wù)執(zhí)行的支持。ExecutorService 提供了安排異步執(zhí)行的方法,可執(zhí)行由 Callable 表示的任何函數(shù),結(jié)果類似于 RunnableFuture 返回函數(shù)的結(jié)果,允許確定執(zhí)行是否完成,并提供取消執(zhí)行的方法。RunnableFuture 是擁有 run 方法的 Future,run 方法執(zhí)行時將設(shè)置其結(jié)果。

    實現(xiàn)。類 ThreadPoolExecutor 和 ScheduledThreadPoolExecutor 提供可調(diào)的、靈活的線程池。Executors 類提供大多數(shù) Executor 的常見類型和配置的工廠方法,以及使用它們的幾種實用工具方法。其他基于 Executor 的實用工具包括具體類 FutureTask,它提供 Future 的常見可擴展實現(xiàn),以及 ExecutorCompletionService,它有助于協(xié)調(diào)對異步任務(wù)組的處理。

    隊列

    java.util.concurrent ConcurrentLinkedQueue 類提供了高效的、可伸縮的、線程安全的非阻塞 FIFO 隊列。java.util.concurrent 中的五個實現(xiàn)都支持擴展的 BlockingQueue 接口,該接口定義了 put 和 take 的阻塞版本:LinkedBlockingQueueArrayBlockingQueueSynchronousQueuePriorityBlockingQueue 和 DelayQueue。這些不同的類覆蓋了生產(chǎn)者-使用者、消息傳遞、并行任務(wù)執(zhí)行和相關(guān)并發(fā)設(shè)計的大多數(shù)常見使用的上下文。BlockingDeque 接口擴展 BlockingQueue,以支持 FIFO 和 LIFO(基于堆棧)操作。LinkedBlockingDeque 類提供一個實現(xiàn)。

    計時

    TimeUnit 類為指定和控制基于超時的操作提供了多重粒度(包括納秒級)。該包中的大多數(shù)類除了包含不確定的等待之外,還包含基于超時的操作。在使用超時的所有情況中,超時指定了在表明已超時前該方法應(yīng)該等待的最少時間。在超時發(fā)生后,實現(xiàn)會“盡力”檢測超時。但是,在檢測超時與超時之后再次實際執(zhí)行線程之間可能要經(jīng)過不確定的時間。接受超時期參數(shù)的所有方法將小于等于 0 的值視為根本不會等待。要“永遠”等待,可以使用 Long.MAX_VALUE 值。

    同步器

    四個類可協(xié)助實現(xiàn)常見的專用同步語句。Semaphore 是一個經(jīng)典的并發(fā)工具。CountDownLatch 是一個極其簡單但又極其常用的實用工具,用于在保持給定數(shù)目的信號、事件或條件前阻塞執(zhí)行。CyclicBarrier 是一個可重置的多路同步點,在某些并行編程風格中很有用。Exchanger 允許兩個線程在 collection 點交換對象,它在多流水線設(shè)計中是有用的。

    并發(fā) Collection

    除隊列外,此包還提供了設(shè)計用于多線程上下文中的 Collection 實現(xiàn):ConcurrentHashMapConcurrentSkipListMapConcurrentSkipListSetCopyOnWriteArrayList 和 CopyOnWriteArraySet。當期望許多線程訪問一個給定 collection 時,ConcurrentHashMap 通常優(yōu)于同步的 HashMapConcurrentSkipListMap 通常優(yōu)于同步的 TreeMap。當期望的讀數(shù)和遍歷遠遠大于列表的更新數(shù)時,CopyOnWriteArrayList 優(yōu)于同步的 ArrayList

    此包中與某些類一起使用的“Concurrent&rdquo前綴;是一種簡寫,表明與類似的“同步”類有所不同。例如,java.util.Hashtable 和Collections.synchronizedMap(new HashMap()) 是同步的,但 ConcurrentHashMap 則是“并發(fā)的”。并發(fā) collection 是線程安全的,但是不受單個排他鎖的管理。在 ConcurrentHashMap 這一特定情況下,它可以安全地允許進行任意數(shù)目的并發(fā)讀取,以及數(shù)目可調(diào)的并發(fā)寫入。需要通過單個鎖不允許對 collection 的所有訪問時,“同步”類是很有用的,其代價是較差的可伸縮性。在期望多個線程訪問公共 collection 的其他情況中,通常“并發(fā)”版本要更好一些。當 collection 是未共享的,或者僅保持其他鎖時 collection 是可訪問的情況下,非同步 collection 則要更好一些。

    大多數(shù)并發(fā) Collection 實現(xiàn)(包括大多數(shù) Queue)與常規(guī)的 java.util 約定也不同,因為它們的迭代器提供了弱一致的,而不是快速失敗的遍歷。弱一致的迭代器是線程安全的,但是在迭代時沒有必要凍結(jié) collection,所以它不一定反映自迭代器創(chuàng)建以來的所有更新。

    內(nèi)存一致性屬性

    Java Language Specification 第 17 章定義了內(nèi)存操作(如共享變量的讀寫)的 happen-before 關(guān)系。只有寫入操作 happen-before 讀取操作時,才保證一個線程寫入的結(jié)果對另一個線程的讀取是可視的。synchronized 和 volatile 構(gòu)造 happen-before 關(guān)系,Thread.start() 和Thread.join() 方法形成 happen-before 關(guān)系。尤其是:
    • 線程中的每個操作 happen-before 稍后按程序順序傳入的該線程中的每個操作。
    • 一個解除鎖監(jiān)視器的(synchronized 阻塞或方法退出)happen-before 相同監(jiān)視器的每個后續(xù)鎖(synchronized 阻塞或方法進入)。并且因為 happen-before 關(guān)系是可傳遞的,所以解除鎖定之前的線程的所有操作 happen-before 鎖定該監(jiān)視器的任何線程后續(xù)的所有操作。
    • 寫入 volatile 字段 happen-before 每個后續(xù)讀取相同字段。volatile 字段的讀取和寫入與進入和退出監(jiān)視器具有相似的內(nèi)存一致性效果,但 需要互斥鎖。
    • 在線程上調(diào)用 start happen-before 已啟動的線程中的任何線程。
    • 線程中的所有操作 happen-before 從該線程上的 join 成功返回的任何其他線程。
    java.util.concurrent 中所有類的方法及其子包擴展了這些對更高級別同步的保證。尤其是:
    • 線程中將一個對象放入任何并發(fā) collection 之前的操作 happen-before 從另一線程中的 collection 訪問或移除該元素的后續(xù)操作。
    • 線程中向 Executor 提交 Runnable 之前的操作 happen-before 其執(zhí)行開始。同樣適用于向 ExecutorService 提交 Callables
    • 異步計算(由 Future 表示)所采取的操作 happen-before 通過另一線程中 Future.get() 獲取結(jié)果后續(xù)的操作。
    • “釋放”同步儲存方法(如 Lock.unlockSemaphore.release 和 CountDownLatch.countDown)之前的操作 happen-before 另一線程中相同同步儲存對象成功“獲取”方法(如 Lock.lockSemaphore.acquireCondition.await 和 CountDownLatch.await)的后續(xù)操作。
    • 對于通過 Exchanger 成功交換對象的每個線程對,每個線程中 exchange() 之前的操作 happen-before 另一線程中對應(yīng) exchange() 后續(xù)的操作。
    • 調(diào)用 CyclicBarrier.await 之前的操作 happen-before 屏障操作所執(zhí)行的操作,屏障操作所執(zhí)行的操作 happen-before 從另一線程中對應(yīng)await 成功返回的后續(xù)操作。

     

    Condition

    Condition 將 Object 監(jiān)視器方法(waitnotify 和 notifyAll)分解成截然不同的對象,以便通過將這些對象與任意 Lock 實現(xiàn)組合使用,為每個對象提供多個等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和語句的使用,Condition 替代了 Object 監(jiān)視器方法的使用。

    條件(也稱為條件隊列 或條件變量)為線程提供了一個含義,以便在某個狀態(tài)條件現(xiàn)在可能為 true 的另一個線程通知它之前,一直掛起該線程(即讓其“等待”)。因為訪問此共享狀態(tài)信息發(fā)生在不同的線程中,所以它必須受保護,因此要將某種形式的鎖與該條件相關(guān)聯(lián)。等待提供一個條件的主要屬性是:以原子方式 釋放相關(guān)的鎖,并掛起當前線程,就像 Object.wait 做的那樣。

    Condition 實例實質(zhì)上被綁定到一個鎖上。要為特定 Lock 實例獲得 Condition 實例,請使用其 newCondition() 方法。

    作為一個示例,假定有一個綁定的緩沖區(qū),它支持 put 和 take 方法。如果試圖在空的緩沖區(qū)上執(zhí)行 take 操作,則在某一個項變得可用之前,線程將一直阻塞;如果試圖在滿的緩沖區(qū)上執(zhí)行 put 操作,則在有空間變得可用之前,線程將一直阻塞。我們喜歡在單獨的等待 set 中保存 put 線程和 take 線程,這樣就可以在緩沖區(qū)中的項或空間變得可用時利用最佳規(guī)劃,一次只通知一個線程。可以使用兩個 Condition 實例來做到這一點。

     class BoundedBuffer {
       final Lock lock = new ReentrantLock();
       final Condition notFull  = lock.newCondition(); 
       final Condition notEmpty = lock.newCondition(); 
    
       final Object[] items = new Object[100];
       int putptr, takeptr, count;
    
       public void put(Object x) throws InterruptedException {
         lock.lock();
         try {
           while (count == items.length) 
             notFull.await();
           items[putptr] = x; 
           if (++putptr == items.length) putptr = 0;
           ++count;
           notEmpty.signal();
         } finally {
           lock.unlock();
         }
       }
    
       public Object take() throws InterruptedException {
         lock.lock();
         try {
           while (count == 0) 
             notEmpty.await();
           Object x = items[takeptr]; 
           if (++takeptr == items.length) takeptr = 0;
           --count;
           notFull.signal();
           return x;
         } finally {
           lock.unlock();
         }
       } 
     }
     
    
    
    ArrayBlockingQueue 類提供了這項功能,因此沒有理由去實現(xiàn)這個示例類。)

    Condition 實現(xiàn)可以提供不同于 Object 監(jiān)視器方法的行為和語義,比如受保證的通知排序,或者在執(zhí)行通知時不需要保持一個鎖。如果某個實現(xiàn)提供了這樣特殊的語義,則該實現(xiàn)必須記錄這些語義。

    注意,Condition 實例只是一些普通的對象,它們自身可以用作 synchronized 語句中的目標,并且可以調(diào)用自己的 wait 和notification 監(jiān)視器方法。獲取 Condition 實例的監(jiān)視器鎖或者使用其監(jiān)視器方法,與獲取和該 Condition 相關(guān)的 Lock 或使用其 waiting 和 signalling 方法沒有什么特定的關(guān)系。為了避免混淆,建議除了在其自身的實現(xiàn)中之外,切勿以這種方式使用Condition 實例。

    除非另行說明,否則為任何參數(shù)傳遞 null 值將導致拋出 NullPointerException

    實現(xiàn)注意事項

    在等待 Condition 時,允許發(fā)生“虛假喚醒”,這通常作為對基礎(chǔ)平臺語義的讓步。對于大多數(shù)應(yīng)用程序,這帶來的實際影響很小,因為 Condition 應(yīng)該總是在一個循環(huán)中被等待,并測試正被等待的狀態(tài)聲明。某個實現(xiàn)可以隨意移除可能的虛假喚醒,但建議應(yīng)用程序程序員總是假定這些虛假喚醒可能發(fā)生,因此總是在一個循環(huán)中等待。

    三種形式的條件等待(可中斷、不可中斷和超時)在一些平臺上的實現(xiàn)以及它們的性能特征可能會有所不同。尤其是它可能很難提供這些特性和維護特定語義,比如排序保證。更進一步地說,中斷線程實際掛起的能力在所有平臺上并不是總是可行的。

    因此,并不要求某個實現(xiàn)為所有三種形式的等待定義完全相同的保證或語義,也不要求其支持中斷線程的實際掛起。

    要求實現(xiàn)清楚地記錄每個等待方法提供的語義和保證,在某個實現(xiàn)不支持中斷線程的掛起時,它必須遵從此接口中定義的中斷語義。

    由于中斷通常意味著取消,而又通常很少進行中斷檢查,因此實現(xiàn)可以先于普通方法的返回來對中斷進行響應(yīng)。即使出現(xiàn)在另一個操作后的中斷可能會釋放線程鎖時也是如此。實現(xiàn)應(yīng)記錄此行為。





    http://blog.csdn.net/fh13760184/article/details/8551546#
    posted @ 2013-03-21 16:03 abin 閱讀(2368) | 評論 (3)編輯 收藏

    僅列出標題
    共50頁: First 上一頁 14 15 16 17 18 19 20 21 22 下一頁 Last 
    主站蜘蛛池模板: 亚洲精品在线视频观看| 亚洲欭美日韩颜射在线二| 亚洲毛片基地日韩毛片基地| 男女交性无遮挡免费视频| 国产免费观看视频| 黄色片网站在线免费观看| 免费大黄网站在线观| 免费无码午夜福利片| 四虎免费永久在线播放| 久久久久久久久久免免费精品| 中文字幕不卡亚洲| 人妻免费一区二区三区最新| 亚洲国产精品lv| 成人免费一级毛片在线播放视频 | 免费看无码自慰一区二区| 亚洲第一成年网站视频| 免费播放特黄特色毛片| 日本高清不卡aⅴ免费网站| 久久精品国产精品亚洲毛片| 在线不卡免费视频| 免费人成大片在线观看播放电影| 中文字幕亚洲综合久久菠萝蜜| 污污网站18禁在线永久免费观看| 337p日本欧洲亚洲大胆艺术| 麻豆国产精品入口免费观看| 少妇亚洲免费精品| 亚洲bt加勒比一区二区| 国产精品成人免费一区二区| 美女露100%胸无遮挡免费观看| 亚洲熟妇无码AV在线播放 | 在线视频免费国产成人| 一级毛片a女人刺激视频免费 | 久久青青草原亚洲av无码| 久久国产精品免费专区| 国产人成亚洲第一网站在线播放| 免费a级毛片18以上观看精品| 男人都懂www深夜免费网站| 久久亚洲精品国产精品婷婷| 亚洲一区二区女搞男| 无码国产精品久久一区免费| jizz免费观看视频|