zoukankan      html  css  js  c++  java
  • 面试-准备

    深入理解java虚拟机
    http://www.cnblogs.com/prayers/p/5515245.html

    spring面试题
    http://www.importnew.com/15851.html

    sed 's/原字符串/替换字符串/'  末尾加g替换每一个匹配的关键字,否则只替换每行的第一个
    cat /etc/passwd |awk  -F ':'  '{print $1" "$7}'

    当前WEB服务器中联接次数最多的ip地址
    #netstat -ntu |awk '{print $5}' |sort | uniq -c| sort -nr
    查看日志中访问次数最多的前10个IP
    #cat access_log |cut -d ' ' -f 1 | sort |uniq -c | sort -nr | awk '{print $0 }' | head -n 10 | less
    查看日志中出现100次以上的IP
    #cat access_log |cut -d ' ' -f 1 | sort |uniq -c | awk '{if ($1 > 100) print $0}'|sort -nr | less
    查看最近访问量最高的文件
    #cat access_log | tail -10000 | awk '{print $7}' | sort | uniq -c | sort -nr | less
    查看日志中访问超过100次的页面
    #cat access_log | cut -d ' ' -f 7 | sort |uniq -c | awk '{if ($1 > 100) print $0}' | less
    统计某url,一天的访问次数
    #cat access_log | grep '12/Aug/2009' | grep '/images/index/e1.gif' | wc | awk '{print $1}'
    前五天的访问次数最多的网页
    #cat access_log | awk '{print $7}' | uniq -c | sort -n -r | head -20
    从日志里查看该ip在干嘛
    #cat access_log | grep 218.66.36.119 | awk '{print $1" "$7}' | sort | uniq -c | sort -nr | less
    列出传输时间超过 30 秒的文件
    #cat access_log | awk '($NF > 30){print $7}' | sort -n | uniq -c | sort -nr | head -20
    列出最最耗时的页面(超过60秒的)
    #cat access_log | awk '($NF > 60 && $7~/.php/){print $7}' | sort -n | uniq -c | sort -nr | head -100

    (01) ArrayList 实际上是通过一个数组去保存数据的。当我们构造ArrayList时;若使用默认构造函数,则ArrayList的默认容量大小是10。
    (02) 当ArrayList容量不足以容纳全部元素时,ArrayList会重新设置容量:新的容量=“(原始容量x3)/2 + 1”。
    (03) ArrayList的克隆函数,即是将全部元素克隆到一个数组中。
    (04) ArrayList实现java.io.Serializable的方式。当写入到输出流时,先写入“容量”,再依次写入“每一个元素”;当读出输入流时,先读取“容量”,再依次读取“每一个元素”
    ArrayList 是一个数组队列,相当于动态数组。它由数组实现,随机访问效率高,随机插入、随机删除效率低。
    LinkedList 是一个双向链表。它也可以被当作堆栈、队列或双端队列进行操作。LinkedList随机访问效率低,但随机插入、随机删除效率低。

    hashMap
    1.HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体
    初始容量,加载因子
    对key做null检查,如果key是null,会被存储到table[0],因为null的hash值总是0
    HashMap和Hashtable都是存储“键值对(key-value)”的散列表,而且都是采用拉链法实现的。
    存储的思想都是:通过table数组存储,数组的每一个元素都是一个Entry;而一个Entry就是一个单向链表,Entry链表中的每一个节点就保存了key-value键值对数据。
    添加key-value键值对:首先,根据key值计算出哈希值,再计算出数组索引(即,该key-value在table中的索引)。然后,根据数组索引找到Entry(即,单向链表),再遍历单向链表,将key和链表中的每一个节点的key进行对比。若key已经存在Entry链表中,则用该value值取代旧的value值;若key不存在Entry链表中,则新建一个key-value节点,并将该节点插入Entry链表的表头位置。
    删除key-value键值对:删除键值对,相比于“添加键值对”来说,简单很多。首先,还是根据key计算出哈希值,再计算出数组索引(即,该key-value在table中的索引)。然后,根据索引找出Entry(即,单向链表)。若节点key-value存在与链表Entry中,则删除链表中的节点即可。、

    ConcurrentHashMap是线程安全的哈希表,它是通过“锁分段”来实现的。ConcurrentHashMap中包括了“Segment(锁分段)数组”,每个Segment就是一个哈希表,而且也是可重入的互斥锁。第一,Segment是哈希表表现在,Segment包含了“HashEntry数组”,而“HashEntry数组”中的每一个HashEntry元素是一个单向链表。即Segment是通过链式哈希表。第二,Segment是可重入的互斥锁表现在,Segment继承于ReentrantLock,而ReentrantLock就是可重入的互斥锁。
    对于ConcurrentHashMap的添加,删除操作,在操作开始前,线程都会获取Segment的互斥锁;操作完毕之后,才会释放。而对于读取操作,它是通过volatile去实现的,HashEntry数组是volatile类型的,而volatile能保证“即对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写入”,即我们总能读到其它线程写入HashEntry之后的值。
    大于或等于concurrencyLevel的最小的2的N次方值

    ArrayBlockingQueue若某线程(线程A)要取出数据时,队列正好为空,则该线程会执行notEmpty.await()进行等待;当其它某个线程(线程B)向队列中插入了数据之后,会调用notEmpty.signal()唤醒“notEmpty上的等待线程”。此时,线程A会被唤醒从而得以继续运行。 此外,线程A在执行取操作前,会获取takeLock,在取操作执行完毕再释放takeLock。
    若某线程(线程H)要插入数据时,队列已满,则该线程会它执行notFull.await()进行等待;当其它某个线程(线程I)取出数据之后,会调用notFull.signal()唤醒“notFull上的等待线程”。此时,线程H就会被唤醒从而得以继续运行。 此外,线程H在执行插入操作前,会获取putLock,在插入操作执行完毕才释放putLock。

    一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该Session中的所有 Cache 就将清空。
    二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。
    对于缓存数据更新机制,当某一个作用域(一级缓存Session/二级缓存Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被clear。

    1)CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同:
    CountDownLatch一般用于某个线程A等待若干个其他线程执行完任务之后,它才执行;
    而CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行;
    另外,CountDownLatch是不能够重用的,而CyclicBarrier是可以重用的。
    2)Semaphore其实和锁有点类似,它一般用于控制对某组资源的访问权限。


    ThreadPoolExecutor 线程池任务执行流程:
        当线程池小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程。
        当线程池达到corePoolSize时,新提交任务将被放入workQueue中,等待线程池中任务调度执行
        当workQueue已满,且maximumPoolSize>corePoolSize时,新提交任务会创建新线程执行任务
        当提交任务数超过maximumPoolSize时,新提交任务由RejectedExecutionHandler处理
        当线程池中超过corePoolSize线程,空闲时间达到keepAliveTime时,关闭空闲线程
        当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭

    排队
    1.直接提交。工作队列的默认选项是 SynchronousQueue,它将任务直接提交给线程而不保持它们。
    2.无界队列。使用无界队列(例如,不具有预定义容量的 LinkedBlockingQueue)将导致在所有 corePoolSize 线程都忙时新任务在队列中等待。这样,创建的线程就不会超过 corePoolSize。
    3.有界队列。当使用有限的 maximumPoolSizes 时,有界队列(如 ArrayBlockingQueue)有助于防止资源耗尽,但是可能较难调整和控制

    被拒绝的任务
    当 Executor 已经关闭,并且 Executor 将有限边界用于最大线程和工作队列容量,且已经饱和时,在方法 execute(java.lang.Runnable) 中提交的新任务将被拒绝

    1.在默认的 ThreadPoolExecutor.AbortPolicy 中,处理程序遭到拒绝将抛出运行时RejectedExecutionException。
    2.在 ThreadPoolExecutor.CallerRunsPolicy 中,线程调用运行该任务的execute 本身。此策略提供简单的反馈控制机制,能够减缓新任务的提交速度。
    3.在 ThreadPoolExecutor.DiscardPolicy 中,不能执行的任务将被删除。
    4.在 ThreadPoolExecutor.DiscardOldestPolicy 中,如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序(如果再次失败,则重复此过程)。

    newCachedThreadPool:
        底层:返回ThreadPoolExecutor实例,corePoolSize为0;maximumPoolSize为Integer.MAX_VALUE;keepAliveTime为60L;unit为TimeUnit.SECONDS;workQueue为SynchronousQueue(同步队列)
        通俗:当有新任务到来,则插入到SynchronousQueue中,由于SynchronousQueue是同步队列,因此会在池中寻找可用线程来执行,若有可以线程则执行,若没有可用线程则创建一个线程来执行该任务;若池中线程空闲时间超过指定大小,则该线程会被销毁。
        适用:执行很多短期异步的小程序或者负载较轻的服务器
    newFixedThreadPool:
        底层:返回ThreadPoolExecutor实例,接收参数为所设定线程数量nThread,corePoolSize为nThread,maximumPoolSize为nThread;keepAliveTime为0L(不限时);unit为:TimeUnit.MILLISECONDS;WorkQueue为:new LinkedBlockingQueue<Runnable>() 无解阻塞队列
        通俗:创建可容纳固定数量线程的池子,每隔线程的存活时间是无限的,当池子满了就不在添加线程了;如果池中的所有线程均在繁忙状态,对于新任务会进入阻塞队列中(无界的阻塞队列)
        适用:执行长期的任务,性能好很多
    newSingleThreadExecutor:
        底层:FinalizableDelegatedExecutorService包装的ThreadPoolExecutor实例,corePoolSize为1;maximumPoolSize为1;keepAliveTime为0L;unit为:TimeUnit.MILLISECONDS;workQueue为:new LinkedBlockingQueue<Runnable>() 无解阻塞队列
        通俗:创建只有一个线程的线程池,且线程的存活时间是无限的;当该线程正繁忙时,对于新任务会进入阻塞队列中(无界的阻塞队列)
        适用:一个任务一个任务执行的场景
    NewScheduledThreadPool:
        底层:创建ScheduledThreadPoolExecutor实例,corePoolSize为传递来的参数,maximumPoolSize为Integer.MAX_VALUE;keepAliveTime为0;unit为:TimeUnit.NANOSECONDS;workQueue为:new DelayedWorkQueue() 一个按超时时间升序排序的队列
        通俗:创建一个固定大小的线程池,线程池内线程存活时间无限制,线程池可以支持定时及周期性任务执行,如果所有线程均处于繁忙状态,对于新任务会进入DelayedWorkQueue队列中,这是一种按照超时时间排序的队列结构
        适用:周期性执行任务的场景



    BIO是一个连接一个线程。
    NIO是一个请求一个线程。
    AIO是一个有效请求一个线程。

    先来个例子理解一下概念,以银行取款为例:
        同步 : 自己亲自出马持银行卡到银行取钱(使用同步IO时,Java自己处理IO读写);
        异步 : 委托一小弟拿银行卡到银行取钱,然后给你(使用异步IO时,Java将IO读写委托给OS处理,需要将数据缓冲区地址和大小传给OS(银行卡和密码),OS需要支持异步IO操作API);
        阻塞 : ATM排队取款,你只能等待(使用阻塞IO时,Java调用会一直阻塞到读写完成才返回);
        非阻塞 : 柜台取款,取个号,然后坐在椅子上做其它事,等号广播会通知你办理,没到号你就不能去,你可以不断问大堂经理排到了没有,大堂经理如果说还没到你就不能去(使用非阻塞IO时,如果不能读写Java调用会马上返回,当IO事件分发器会通知可读写时再继续进行读写,不断循环直到读写完成)

    Java对BIO、NIO、AIO的支持:
        Java BIO : 同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。
        Java NIO : 同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。
        Java AIO(NIO.2) : 异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理,

     同步阻塞IO:在此种方式下,用户进程在发起一个IO操作以后,必须等待IO操作的完成,只有当真正完成了IO操作以后,用户进程才能运行。JAVA传统的IO模型属于此种方式!
    同步非阻塞IO:在此种方式下,用户进程发起一个IO操作以后边可返回做其它事情,但是用户进程需要时不时的询问IO操作是否就绪,这就要求用户进程不停的去询问,从而引入不必要的CPU资源浪费。其中目前JAVA的NIO就属于同步非阻塞IO。
    异步阻塞IO:此种方式下是指应用发起一个IO操作以后,不等待内核IO操作的完成,等内核完成IO操作以后会通知应用程序,这其实就是同步和异步最关键的区别,同步必须等待或者主动的去询问IO是否完成,那么为什么说是阻塞的呢?因为此时是通过select系统调用来完成的,而select函数本身的实现方式是阻塞的,而采用select函数有个好处就是它可以同时监听多个文件句柄,从而提高系统的并发性!

     异步非阻塞IO:在此种模式下,用户进程只需要发起一个IO操作然后立即返回,等IO操作真正的完成以后,应用程序会得到IO操作完成的通知,此时用户进程只需要对数据进行处理就好了,不需要进行实际的IO读写操作,因为真正的IO读取或者写入操作已经由内核完成了。目前Java中还没有支持此种IO模型。


    如果你想吃一份宫保鸡丁盖饭:
    同步阻塞:你到饭馆点餐,然后在那等着,还要一边喊:好了没啊!
    同步非阻塞:在饭馆点完餐,就去遛狗了。不过溜一会儿,就回饭馆喊一声:好了没啊!
    异步阻塞:遛狗的时候,接到饭馆电话,说饭做好了,让您亲自去拿。
    异步非阻塞:饭馆打电话说,我们知道您的位置,一会给你送过来,安心遛狗就可以了。


    3.springmvc
    第一步:发起请求到前端控制器(DispatcherServlet)
    第二步:前端控制器请求HandlerMapping查找 Handler
             可以根据xml配置、注解进行查找
    第三步:处理器映射器HandlerMapping向前端控制器返回Handler
    第四步:前端控制器调用处理器适配器去执行Handler
    第五步:处理器适配器去执行Handler
    第六步:Handler执行完成给适配器返回ModelAndView
    第七步:处理器适配器向前端控制器返回ModelAndView
             ModelAndView是springmvc框架的一个底层对象,包括Model和view
    第八步:前端控制器请求视图解析器去进行视图解析
            根据逻辑视图名解析成真正的视图(jsp)
    第九步:视图解析器向前端控制器返回View
    第十步:前端控制器进行视图渲染
             视图渲染将模型数据(在ModelAndView对象中)填充到request域
    第十一步:前端控制器向用户响应结果

    maven总结
    maven解决jar冲突
    1.dependency:tree 以层级树方式展现传递性依赖
    2.<exclusion> 将不想要的传递依赖剪除掉
    3.查看运行期类来源的JAR包


    事务属性
    传播行为 隔离规则 回滚规则 事务超时 是否只读

    spring 事务传播
    REQUIRED 表示当前方法必须运行在事务中。如果当前事务存在,方法将会在该事务中运行。否则,会启动一个新的事务
    SUPPORTS 表示当前方法不需要事务上下文,但是如果存在当前事务的话,那么该方法会在这个事务中运行
    MANDATORY     表示该方法必须在事务中运行,如果当前事务不存在,则会抛出一个异常
    REQUIRED_NEW     表示当前方法必须运行在它自己的事务中。一个新的事务将被启动。如果存在当前事务,在该方法执行期间,当前事务会被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager
    NOT_SUPPORTED     表示该方法不应该运行在事务中。如果存在当前事务,在该方法运行期间,当前事务将被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager
    NEVER     表示当前方法不应该运行在事务上下文中。如果当前正有一个事务在运行,则会抛出异常
    NESTED     表示如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行

    脏读(Dirty reads)——脏读发生在一个事务读取了另一个事务改写但尚未提交的数据时。如果改写在稍后被回滚了,那么第一个事务获取的数据就是无效的。
    不可重复读(Nonrepeatable read)——不可重复读发生在一个事务执行相同的查询两次或两次以上,但是每次都得到不同的数据时。这通常是因为另一个并发事务在两次查询期间进行了更新。
    幻读(Phantom read)——幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录。

    不可重复读的重点是修改,幻读的重点在于新增或者删除
    从控制的角度来看, 两者的区别就比较大。
    对于前者, 只需要锁住满足条件的记录。
    对于后者, 要锁住满足条件及其相近的记录

    隔离级别
    定义了一个事务可能受其他并发事务影响的程度
    SOLATION_READ_UNCOMMITTED     最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
    ISOLATION_READ_COMMITTED     允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
    ISOLATION_REPEATABLE_READ     对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生
    ISOLATION_SERIALIZABLE     最高的隔离级别,完全服从ACID的隔离级别,确保阻止脏读、不可重复读以及幻读,也是最慢的事务隔离级别,因为它通常是通过完全锁定事务相关的数据库表来实现的



    JVM常见配置
    堆设置
    -Xms:初始堆大小
    -Xmx:最大堆大小
    -XX:NewSize=n:设置年轻代大小
    -XX:NewRatio=n:设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4
    -XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5
    -XX:MaxPermSize=n:设置持久代大小
    收集器设置
    -XX:+UseSerialGC:设置串行收集器
    -XX:+UseParallelGC:设置并行收集器
    -XX:+UseParalledlOldGC:设置并行年老代收集器
    -XX:+UseConcMarkSweepGC:设置并发收集器
    垃圾回收统计信息
    -XX:+PrintGC
    -XX:+PrintGCDetails
    -XX:+PrintGCTimeStamps
    -Xloggc:filename

    并行收集器设置
    -XX:ParallelGCThreads=n:设置并行收集器收集时使用的CPU数。并行收集线程数。
    -XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间
    -XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)

    并发收集器设置
    -XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况。
    -XX:ParallelGCThreads=n:设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。

    spring 配置双数据源并读写分离
    关键思想在于重写 AbstractRoutingSource.determineCurrentLookupKey();
    配置writeDataSource,readDataSource
    aop配置根据方法名前缀选择使用的数据源<entry key="read" value=",get,select,count,list,query," />
    <entry key="write" value=",add,insert,create,update,delete,remove," />

    实现@DataSource注解,在方法上配置


    Redis是一个开源的,基于内存的结构化数据存储媒介,可以作为数据库、缓存服务或消息服务使用。
    Redis支持多种数据结构,包括字符串 string、哈希表 hash、链表list、集合set、有序集合sorted set、位图、Hyperloglogs等。
    Redis具备LRU淘汰、事务实现、以及不同级别的硬盘持久化等能力,并且支持副本集和通过Redis Sentinel实现的高可用方案,同时还支持通过Redis Cluster实现的数据自动分片能力。
    Redis的主要功能都基于单线程模型实现,也就是说Redis使用一个线程来服务所有的客户端请求,同时Redis采用了非阻塞式IO,并精细地优化各种命令的算法时间复杂度
    前文提到过,Redis采用单线程模型,天然是线程安全的,这使得INCR/DECR命令可以非常便利的实现高并发场景下的精确控制。


    1 Dubbo中zookeeper做注册中心,如果注册中心集群都挂掉,发布者和订阅者之间还能通信么?
    可以的,启动dubbo时,消费者会从zk拉取注册的生产者的地址接口等数据,缓存在本地。每次调用时,按照本地存储的地址进行调用

    注册中心对等集群,任意一台宕掉后,会自动切换到另一台
    注册中心全部宕掉,服务提供者和消费者仍可以通过本地缓存通讯
    服务提供者无状态,任一台 宕机后,不影响使用
    服务提供者全部宕机,服务消费者会无法使用,并无限次重连等待服务者恢复
    2 dubbo连接注册中心和直连的区别
    在开发及测试环境下,经常需要绕过注册中心,只测试指定服务提供者,这时候可能需要点对点直连,
    点对点直联方式,将以服务接口为单位,忽略注册中心的提供者列表,

    服务注册中心,动态的注册和发现服务,使服务的位置透明,并通过在消费方获取服务提供方地址列表,实现软负载均衡和Failover, 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
    服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,服务消费者向注册中心获取服务提供者地址列表,并根据负载算法直接调用提供者,注册中心,服务提供者,服务消费者三者之间均为长连接,监控中心除外,注册中心通过长连接感知服务提供者的存在,服务提供者宕机,注册中心将立即推送事件通知消费者
    注册中心和监控中心全部宕机,不影响已运行的提供者和消费者,消费者在本地缓存了提供者列表
    注册中心和监控中心都是可选的,服务消费者可以直连服务提供者

    3、Dubbo在安全机制方面是如何解决的
    Dubbo通过Token令牌防止用户绕过注册中心直连,然后在注册中心上管理授权。Dubbo还提供服务黑白名单,来控制服务所允许的调用方

    4 Dubbo提供了4种均衡策略,如:Random LoadBalance(随机均衡算法)、;RoundRobin LoadBalance(权重轮循均衡算法)、LeastAction LoadBalance(最少活跃调用数均衡算法)、ConsistentHash LoadBalance(一致性Hash均衡算法)

    5 集群容错模式:
    Failover Cluster
    失败自动切换,当出现失败,重试其它服务器。(缺省)
    通常用于读操作,但重试会带来更长延迟。
    可通过retries="2"来设置重试次数(不含第一次)。正是文章刚开始说的那种情况.

     Failfast Cluster
    快速失败,只发起一次调用,失败立即报错。
    通常用于非幂等性的写操作,比如新增记录。

      Failsafe Cluster
    失败安全,出现异常时,直接忽略。
    通常用于写入审计日志等操作。

      Failback Cluster
    失败自动恢复,后台记录失败请求,定时重发。
    通常用于消息通知操作。
      Forking Cluster
    并行调用多个服务器,只要一个成功即返回。
    通常用于实时性要求较高的读操作,但需要浪费更多服务资源。
    可通过forks="2"来设置最大并行数。
      Broadcast Cluster
    广播调用所有提供者,逐个调用,任意一台报错则报错。(2.1.0开始支持)
    通常用于通知所有提供者更新缓存或日志等本地资源信息。

  • 相关阅读:
    18、led驱动程序的实现
    17、字符设备控制技术
    16、驱动访问大揭秘
    14、字符驱动编程模型
    个人开发—进度记录(一)
    个人开发—需求
    学习进度条
    敏捷开发第二阶段个人(七)
    敏捷开发第二阶段个人(六)
    敏捷开发第二阶段个人(五)
  • 原文地址:https://www.cnblogs.com/junge/p/7678364.html
Copyright © 2011-2022 走看看