DPDK mbuf何时释放回非页面缓冲池内存泄漏池

DPDK将利用hugepage预留的物理内存统一的组织管理起来,然后以库的方式对外提供使用的接口。下图展示了DPDK中内存有关的模块的相互关系。
rte_eal&&&&&&&&&&& 是统一的组织管理者(当然rte_eal不只是做内存的工作)
rte_malloc&&&&&& 对外提供分配释放内存的API,分配的内存都是rte_eal中管理的内存
rte_ring&&&&&&&&& 提供无锁队列,他之间使用了rte_eal管理的内存
rte_mempool& 利用rte_eal中的内存和rte_ring提供内存池的功能
ret_mbuf&&&&&&&
下面我们一个一个分析各个模块是怎样处理及使用内存的(重点诉说流程,不会详细的介绍代码),DPDK管理的内存有个很有用的特点--同一块物理内存在不同的进程地址空间中,虚拟地址是一样的。下面会详细的说明DPDK是怎样实现这个功能的。
首先hugepage这里就不描述了,要理解DPDK的内存管理必须知道hugepage,不了解的自行补齐吧,linux内核中有个文档介绍的很详细。可以点击查看。
2 rte_eal 对内存的组织与管理
这块是在rte_eal中实现的。有关的函数有:
rte_eal_init -& eal_hugepage_info_init
rte_eal_init -& rte_eal_memory_init
rte_eal_init -& rte_eal_memzone_init
rte_eal_init -& eal_check_mem_on_local_socket
2.1 eal_hugepage_info_init
首先DPDK管理的内存都是通过hugepage预留的,这个函数主要获取预留的内存的信息,获取方法是读取 /sys/kernel/mm/hugepages 下的文件,具体还是参考hugepage的文档吧,这里不详细描述。
预留的内存按页大小分类( i386 architecture supports 4K and 4M (2M in PAE mode) page sizes, ia64 architecture supports multiple page sizes 4K, 8K, 64K, 256K, 1M, 4M, 16M, 256M and ppc64 supports 4K and 16M. ),可能会有多类,DPDK会把这些信息全部读取,使用struct hugepage_info进行保存,每一类对应一个struct hugepage_info类型的对象,所有的这些对象保存在struct internal_config的数组中。DPDK有个internal_config的全局变量,记录这些信息。
struct hugepage_info {
size_t hugepage_
/**& size of a huge page */
const char *
/**& dir where hugetlbfs is mounted */
uint32_t num_pages[RTE_MAX_NUMA_NODES];
/**& number of hugepages of that size on each socket */
/**& file descriptor for hugepage dir */
struct internal_config {   ...
unsigned num_hugepage_
/**& how many sizes on this system */
struct hugepage_info hugepage_info[MAX_HUGEPAGE_SIZES];
struct internal_config internal_
总结 eal_hugepage_info_init,就是获取了系统中预留的内存信息,有几类(相同页大小的是一类),将每一类的信息(页大小、页数、挂载点)存储在internal_config.hugepage_info数组中。hugepage_info数组也进行了排序,大页的信息放前面,小页的信息放后面。
每一类所有内存页,也分处在哪个 socket上(不明白的查看NUMA相关知识补齐)的,hugepage_info中统计内存页数会按属于处在哪个socket上进行统计,但在这一步(eal_hugepage_info_init)中,还区分不了每个页处在哪个socket上,因此这里还没有按socket统计页数,将内存页数直接记录到num_pages[0]里面了。
2.2 rte_eal_memory_init
rte_eal_memory_init(void)
RTE_LOG(INFO, EAL, "Setting up memory...\n");
const int retval = rte_eal_process_type() == RTE_PROC_PRIMARY ?
rte_eal_hugepage_init() :
rte_eal_hugepage_attach();
if (retval & 0)
return -1;
if (internal_config.no_shconf == 0 && rte_eal_memdevice_init() & 0)
return -1;
DPDK多进程状态下,分为RTE_PROC_PRIMARY进程及RTE_PROC_SECONDARY进程,RTE_PROC_PRIMARY负责初始化内存,RTE_PROC_SECONDARY获取 RTE_PROC_PRIMARY 内存映射的信息,创建与RTE_PROC_PRIMARY一样的内存映射。这是DPDK多进程共享内存的方式。此处先不展开描述。随着流程的展开,自然会明白。
2.2.1 rte_eal_mem_init -& rte_eal_hugepage_init&
DPDK有个全局变量
static struct rte_config rte_config
该变量的成员 struct rte_mem_config *mem_& 保存了DPDK管理的内存的所有信息。DPDK将内存统一的管理,就是将所有内存保存到mem_config:memseg[]中。
struct rte_mem_config {
volatile uint32_
/**& Magic number - Sanity check. */
/* memory topology */
/**& Number of channels (0 if unknown). */
/**& Number of ranks (0 if unknown). */
* current lock nest order
- qlock-&mlock (ring/hash/lpm)
- mplock-&qlock-&mlock (mempool)
*ALWAYS* obtain qlock first if having to obtain both qlock and mlock
rte_rwlock_
/**& only used by memzone LIB for thread-safe. */
rte_rwlock_
/**& used for tailq operation for thread safe. */
rte_rwlock_
/**& only used by mempool LIB for thread-safe. */
uint32_t memzone_ /**& Index of memzone */
/* memory segments and zones */
struct rte_memseg memseg[RTE_MAX_MEMSEG];
/**& Physmem descriptors. */
struct rte_memzone memzone[RTE_MAX_MEMZONE]; /**& Memzone descriptors. */
/* Runtime Physmem descriptors. */
struct rte_memseg free_memseg[RTE_MAX_MEMSEG];
struct rte_tailq_head tailq_head[RTE_MAX_TAILQ]; /**& Tailqs for objects */
/* Heaps of Malloc per socket */
struct malloc_heap malloc_heaps[RTE_MAX_NUMA_NODES];
} __attribute__((__packed__));
详细流程:
函数先根据 struct hugepage_info hugepage_info[MAX_HUGEPAGE_SIZES]; (eal_hugepage_info_init中获取的信息)得到了内存页的总数。然后为struct hugepage_file *tmp_hp申请了内存,有多少个内存页,就分配了多少个hugepage_file。
struct hugepage_file {
void *orig_
/**& virtual addr of first mmap() */
void *final_
/**& virtual addr of 2nd mmap() */
/**& physical addr */
/**& the page size */
int socket_
/**& NUMA socket ID */
/**& the '%d' in HUGEFILE_FMT */
int memseg_
/**& the memory segment to which page belongs */
#ifdef RTE_EAL_SINGLE_FILE_SEGMENTS
/**& number of times the page size is repeated */
char filepath[MAX_HUGEPAGE_PATH]; /**& path to backing file on filesystem */
接着针对每一类内存(相同页大小的内存算一类)进行处理,
for(每一类) {
  for(这一类的每一页) {&&&&&&&&&
    每个页对应一个hugepage_file,file_id,size,filepath初始化。其中file_id是页的序号,这个序号是给filepath用的,是为了给每个页对应的文件起一个独立的文件名(与其他页不会重复)。
    建立文件&filepath&,这个文件是因为使用hugepage的内存必须按这样的方式(先建立文件,再mmap,得到内存虚拟地址使用)使用。
    执行mmap获得页的虚拟地址,赋给hugepage_file:orig_va。
  } (map_all_hugepages())
  所有hugepage预留的物理内存都映射完成,可以根据hugepage_file:orig_va进行访问了。
  for(这一类的每一页) {
    获取物理地址,赋给hugepage_file:physaddr。
    获取物理地址的方式,是linux内核提供的功能,不了解的可以点击补齐。
  }(find_physaddrs())
  for(这一类的每一页) {
     获取每个页所在的socket,赋给hugepage_file:socket_id。 
     获取的方法也是linux内核提供的功能,具体不详述。
  }(find_numasocket())
  对这一类的页的hugepage_file[]按页物理地址进行排序。
  for(这一类的每一页) {
    重新执行mmap,并将获取的虚拟地址赋给hugepage_file:final_va。    
  }(map_all_hugepages())
  本次重新mmap,与第一次的不同是,会主动先申请一块足够映射本类所有内存页的虚拟地址空间,然后将本类的所有页连续的映射的该虚拟地址空间中。
  如果找不到这么大的虚拟地址空间,还是会一页一页的映射,让内核去决定虚拟地址空间。
  第二次映射用代码的注释解释 The second mapping tries to& map continguous physical blocks in contiguous virtual blocks.
  将第一次的映射unmap掉
更新 internal_config.hugepage_info[].num_pages[],我们知道bugepage_info在eal_hugepage_info_init中初始化时,不知道每个页是属于哪个socket的,因此直接使用num_pages[0]记录了所有的页数,但在上一步中,已经知道了每个页属于哪个socket,因此这里更新了num_pages,准确的记录了哪个socket上有多少个页。
这块我还没具体看 unmap pages that we won't need (looks at used_hp),接下来再研究。
接下来,建立了共享内存,将hugepage_file拷贝到共享内存中,这样RTE_PROC_SECONDARY启动后可以在共享内存中读取这些信息,然后创建与RTE_PROC_PRIMARY一致的映射。
最后,使用mem_config-&memseg[]将所有内存管理起来。
一个struct rte_memsg对象,保存一块相同socket的、相同页大小的、物理地址连续的、虚拟地址连续的内存。因此整个内存由多个memseg组成。
总结rte_eal_hugepage_init,它获取hugepge的方式预留的所有物理内存,统一的映射到虚拟地址空间中,保存到memseg中。至此,理论上可以通过memseg获取虚拟地址使用这些内存了。但DPDK提供了统一的方式来使用,不是谁用就可以来拿的。
&2.2.2 rte_eal_mem_init -&&rte_eal_hugepage_attach
&/*&* This creates the memory mappings in the secondary process to match that of&* the server process. It goes through each memory segment in the DPDK runtime&* configuration and finds the hugepages which form that segment, mapping them&* in order to form a contiguous block in the virtual memory space&*/
3 rte_malloc
4 rte_ring
5 rte_mempool
阅读(...) 评论()您所在位置: &
&nbsp&&nbsp&nbsp&&nbsp
DPDK关键技术摘要.doc 27页
本文档一共被下载:
次 ,您可全文免费在线阅读后下载本文档。
下载提示
1.本站不保证该用户上传的文档完整性,不预览、不比对内容而直接下载产生的反悔问题本站不予受理。
2.该文档所得收入(下载+内容+预览三)归上传者、原创者。
3.登录后可充值,立即自动返金币,充值渠道很便利
需要金币:300 &&
你可能关注的文档:
··········
··········
DPDK关键技术
DPDK是INTEL提供的提升数据面报文快速处理速率的应用程序开发包,它主要利用以下几个方面的支持特点来优化报文处理过程,从而加快报文处理速率:
使用大页缓存支持来提高内存访问效率。
利用UIO支持,提供应用空间下驱动程序的支持,也就是说网卡驱动是运行在用户空间的,减下了报文在用户空间和应用空间的多次拷贝。
利用LINUX亲和性支持,把控制面线程及各个数据面线程绑定到不同的CPU核,节省了线程在各个CPU核来回调度。
提供内存池和无锁环形缓存管理,加快内存访问效率。
整个DPDK系统由许多不同组件组成,各组件为应用程序和其它组件提供调用接口,其结构图如下图所示:
Dpdk各系统组件结构图
环境抽象层:为DPDK其它组件和应用程序提供一个屏蔽具体平台特性的统一接口,EAL提供的功能主要有:DPDK加载和启动;支持多核或多线程执行类型;CPU核亲和性处理;原子操作和锁操作接口;时钟参考;PCI总线访问接口;跟踪和调试接口;CPU特性采集接口;中断和告警接口等。
堆内存管理组件(Malloc lib):堆内存管理组件为应用程序提供从大页内存分配堆内存的接口。当需要分配大量内存小块时(如用于存储列表中每个表项指针的内存),使用这些接口可以减少TLB缺页。
环缓冲区管理组件:环缓冲区管理组件为应用程序和其它组件提供一个无锁的多生产者多消费者FIFO队列API。
内存池管理组件:为应用程序和其它组件提供分配内存池的接口,内存池是一个由固定大小的多个内存块组成的内存容器,可用于存储相同对像实体,如报文缓存块等。内存池由内存池的名称(一个字符串)来唯一标识,它由一个环缓中区和一组核本地缓存队列组成,每个核从自已的缓存队列分配内存块,当本地缓存队列减少到一定程度时,从内存环缓冲区中申请内存块来补充本地队列。
网络报文缓存块管理组件:提供应用程序创建和释放用于存储报文信息的缓存块的接口,这些MBUF存储在一内存池中。提供两种类型的MBUF,一种用于存储一般信息,一种用于存储报文数据。
定时器组件:提供一些异步周期执行的接口(也可以只执行一次),可以指定某个函数在规定的时间异步的执行,就像LIBC中的timer定时器,但是这里的定时器需要应用程序在主循环中周期调用rte_timer_manage来使定时器得到执行,使用起来没有那么方便。定时器组件的时间参考来自EAL层提供的时间接口。
除了以上六个核心组件外,DPDK还提供以下功能:
以太网轮询模式驱动(PMD)架构:把以太网驱动从内核移到应用层,采用同步轮询机制而不是内核态的异步中断机制来提高报文的接收和发送效率。
报文转发算法支持:Hash 库和LPM库为报文转发算法提供支持。
网络协议定义和相关宏定义:基于FreeBSD IP协议栈的相关定义如:TCP、UDP、SCTP等协议头定义。
报文QOS调度库:支持随机早检测、流量整形、严格优先级和加权随机循环优先级调度等相关QOS功能。
内核网络接口库(KNI):提供一种DPDK应用程序与内核协议栈的通信的方法,类似普通LINUX的TUN/TAP接口,但比TUN/TAP接口效率高。每个物理网口可以虚拟出多个KNI接口。
以下分章节对各个组件单元进行详细分析。
日志系统篇:
全局日志变量rte_logs
struct rte_logs rte_logs = {
.type = ~0,
.level = RTE_LOG_DEBUG,
.file = NULL,
该变量用于存储日志文件的的FILE指针、日志打印级别、要记录的日志类型。
日志类型:
/* 系统内部日志类型 */
#define RTE_LOGTYPE_EAL
0x /**& Log related to eal. */
#define RTE_LOGTYPE_MALLOC
0x /**& Log related to malloc. */
#define RTE_LOGTYPE_RING
0x /**& Log related to ring. */
#define RTE_LOGTYPE_MEMPOOL 0x /**& Log related to mempool. */
#define RTE_LOGTYPE_TIMER
0x /**& Log related to timers. */
#define RTE_LOGTYPE_PMD
正在加载中,请稍后...当年在某公司实习的时候,当时老大给了我一份DPDK的文档,说是将来很有用,熟悉DPDK对能力提高也有帮助,就试着翻译了
《Intel DPDK Getting Started Guide》和半个《Intel DPDK Programmers Guide》,后来忙着论文就没再搞了。现在,发现
pf_ring的统计虚高了,只好重新拥抱DPDK了。
DPDK的代码量还是很庞大的,分析代码之前理清库里面的各个部分的关系很有必要,下面的一张图很好的表现了各部分关系。
先介绍DPDK中的几个缩写吧:
RTE:Run-Time&Environment&
EAL:Environment Abstraction Layer
PMD: Poll-Mode Driver
Memory Manager (librte_malloc,内存管理器)
Librte_malloc 库提供一组API,用于从hugepages创建的memzones中分配内存而不是在堆中分配。这有助于改善Linux用户空间环境下典型的从堆中大量分配4KB页面而容易引起TLB不命中。
Memory Pool Manager (librte_mempool,内存池管理器)
内存池管理器负责分配的内存中的pool对象。一个pool由名称标识,并使用一个ring来存储空闲对象。它提供了其他一些可选的服务,例如每个core的对象缓存和对齐方式帮助器,以确保将填充的对象在所有内存通道上均匀分布。
Ring Manager (librte_ring,环形队列管理器)
在一个有限大小的表中,ring结构提供了一个无锁的多生产者多消费者的FIFO API。相较于无锁队列,它有一些的优势 ;更容易实现,适应于大容量操作和速度更快。一个ring用在内存池管理器(librte_mempool),也可用作cores和(或)在一个逻辑core之上的连接在一起的执行块的通用沟通机制。
Network Packet Buffer Management (librte_mbuf,网络报文缓冲管理)
mbuf 库提供了创建和销毁缓冲区,英特尔 (R) DPDK 应用程序可能用来存储消息缓冲。创建消息缓冲区在启动时间和存储在 mempool,并使用英特尔 (R) DPDK mempool 库。
此库提供一组 API,用于分配或释放 mbufs,操纵控制消息缓冲区(ctrlmbuf) ——普通的消息缓冲区,还操作数据包缓冲区 (pktmbuf) -——用来进行网络数据包。
Timer Manager (librte_timer,定时器管理)
timer库向英特尔 (R) DPDK 执行单位提供定时器服务,保证以异步方式执行函数的能力。它可以是定期调用,或只是一次性调用。它使用环境抽象层 (EAL) 提供的到的 HPET 接口来获取精确时间的引用,并根据需求在每个核心启动。
上面的介绍有点抽象,还是直接看代码的目录更具体些。
&接下来讲讲DPDK的特点。
阅读(...) 评论()CSDN博客推荐文章
http://blog.csdn.net
http://static.blog.csdn.net/images/logo.gif
CSDN博客内容聚合服务
http://blog.csdn.net
(C) 2011 CSDN.NET
http://blog.csdn.net
第11课 使用子查询
http://blog.csdn.net/rainary/article/details/
http://blog.csdn.net/rainary/article/details/
这一课介绍什么是子查询,如何使用它们。
11.1子查询
SELECT语句是SQL的查询。我们迄今为止所看到的所有SELECT语句都是简单查询,即从单个数据库表中检索数据的单条语句。
查询(query)
任何SQL语句都是查询。但此术语一般指SELECT语句。
SQL还允许创建子查询(subquery),即嵌套在其他查询中的查询。为什么要这样做呢?理解这个概念的最好方法是考察几个例子。
说明:MySQL 支持
如果使用 MySQL,应该知道对子查询的支持是从 4.1 版本引入的。MySQL的早期版本不支持子查询。
11.2利用子查询进行过滤
本书所有课中使用的数据库表都是关系表。订单存储在两个表中。每个订单包含订单编号、客户ID、订单日期,在 Orders 表中存储为一行。各订单的物品存储在相关的OrderItems表中。Orders表不存储顾客信息,只存储顾客ID。顾客的实际信息存储在 Customers表中。
现在,假如需要列出订购物品 RGAN01的所有顾客,应该怎样检索?下面列出具体的步骤。
检索包含物品RGAN01的所有订单的编号。
检索具有前一步骤列出的订单编号的所有顾客的ID。
检索前一步骤返回的所有顾客ID的顾客信息。
上述每个步骤都可以单独作为一个查询来执行。可以把一条 SELECT语句返回的结果用于另一条SELECT语句的WHERE子句。
也可以使用子查询来把3个查询组合成一条语句。
第一条 SELECT语句的含义很明确,它对 prod_id为 RGAN01的所有订单物品,检索其 order_num列。输出列出了两个包含此物品的订单:
SELECT order_num
FROM OrderItems
WHERE prod_id = 'RGAN01';
现在,我们知道了哪个订单包含要检索的物品,下一步查询与订单20007 和20008相关的顾客ID。利用第5课介绍的IN子句,编写如下的SELECT语句:
SELECT cust_id
FROM Orders
WHERE order_num IN (20007,20008);
现在,结合这两个查询,把第一个查询(返回订单号的那一个)变为子查询。请看下面的SELECT语句:
SELECT cust_id
FROM Orders
WHERE order_num IN (SELECT order_num
FROM OrderItems
WHERE prod_id = 'RGAN01');
在 SELECT语句中,子查询总是从内向外处理。在处理上面的SELECT语 句时,DBMS实际上执行了两个操作。
首先,它执行下面的查询:
SELECT order_num FROM orderitems WHERE prod_id=’RGAN01’
此查询返回两个订单号:20007和 20008。然后,这两个值以 IN操作符要求的逗号分隔的格式传递给外部查询的 WHERE 子句。外部查询变成:
SELECT cust_id FROM orders WHERE order_num IN ()
可以看到,输出是正确的,与前面硬编码 WHERE子句所返回的值相同。
提示:格式化SQL
包含子查询的 SELECT语句难以阅读和调试,它们在较为复杂时更是如此。如上所示,把子查询分解为多行并进行适当的缩进,能极大地简化子查询的使用。
顺便一提,这就是颜色编码起作用的地方,好的DBMS客户端正是出于这个原因使用了颜色代码SQL。
现在得到了订购物品 RGAN01的所有顾客的 ID。下一步是检索这些顾客ID的顾客信息。检索两列的SQL语句为:
SELECT cust_name, cust_contact
FROM Customers
WHERE cust_id IN ('','');
可以把其中的 WHERE子句转换为子查询,而不是硬编码这些顾客ID:
SELECT cust_name, cust_contact
FROM Customers
WHERE cust_id IN (SELECT cust_id
FROM Orders
WHERE order_num IN (SELECT order_num
FROM OrderItems
WHERE prod_id = 'RGAN01')
cust_contact
Denise L. Stephens
Store Kim Howard
为了执行上述 SELECT语句,DBMS实际上必须执行三条SELECT语句。最里边的子查询返回订单号列表,此列表用于其外面的子查询的 WHERE 子句。外面的子查询返回顾客 ID列表,此顾客 ID列表用于最外层查询的WHERE子句。最外层查询返回所需的数据。
可见,在WHERE子句中使用子查询能够编写出功能很强且很灵活的SQL 语句。对于能嵌套的子查询的数目没有限制,不过在实际使用时由于性能的限制,不能嵌套太多的子查询。
注意:只能是单列
作为子查询的 SELECT语句只能查询单个列。企图检索多个列将返回错误。
注意:子查询和性能
这里给出的代码有效,并且获得了所需的结果。但是,使用子查询并不总是执行这类数据检索的最有效方法。更多的论述,请参阅第12课,其中将再次给出这个例子。
11.3作为计算字段使用子查询
使用子查询的另一方法是创建计算字段。假如需要显示 Customers表中每个顾客的订单总数。订单与相应的顾客ID存储在Orders表中。
执行这个操作,要遵循下面的步骤:
(1)从 Customers表中检索顾客列表;
(2)对于检索出的每个顾客,统计其在Orders表中的订单数目。
正如前两课所述,可以使用 SELECT COUNT(*)对表中的行进行计数,并且通过提供一条WHERE子句来过滤某个特定的顾客ID,仅对该顾客的订 单进行计数。例如,下面的代码对顾客的订单进行计数:
SELECT COUNT(*) AS orders
FROM Orders
WHERE cust_id = '';
要对每个顾客执行COUNT(*),应该将它作为一个子查询。请看下面的代码:
SELECT cust_name,
cust_state,
(SELECT COUNT(*)
FROM Orders
WHERE Orders.cust_id = Customers.cust_id) AS orders
FROM Customers
ORDER BY cust_
cust_state
Kids Place
The Toy Store
Village Toys
这条 SELECT语句对 Customers表中每个顾客返回三列:cust_name、cust_state和 orders。orders是一个计算字段,它是由圆括号中的子查询建立的。该子查询对检索出的每个顾客执行一次。在此例中,该子查询执行了5次,因为检索出了5个顾客。
子查询中的WHERE子句与前面使用的WHERE子句稍有不同,因为它使用了完全限定列名,而不只是列名(cust_id)。它指定表名和列名(Orders.cust_id和Customers.cust_id)。下面的WHERE子句告诉SQL,
比较Orders表中的cust_id和当前正从Customers表中检索的cust_id:
WHERE Orders.cust_id = Customers.cust_id
用一个句点分隔表名和列名,在有可能混淆列名时必须使用这种语法。在这个例子中,有两个 cust_id列:一个在 Customers中,另一个在Orders中。如果不采用完全限定列名,DBMS会认为要对Orders表中的 cust_id自身进行比较。因为SELECT COUNT(*) FROM Orders WHERE cust_id = cust_id总是返回 Orders表中订单的总数,而这个结果不是我们想要的:
SELECT cust_name,
cust_state,
(SELECT COUNT(*)
FROM Orders
WHERE cust_id = cust_id) AS orders
FROM Customers
ORDER BY cust_
cust_state
Kids Place
The Toy Store
Village Toys
虽然子查询在构造这种SELECT语句时极有用,但必须注意限制有歧义的列。
注意:完全限定列名
你已经看到了为什么要使用完全限定列名,没有具体指定就会返回错误结果,因为DBMS会误解你的意思。有时候,由于出现冲突列名而导致的歧义性,会引起DBMS抛出错误信息。例如,WHERE或 ORDER BY子句指定的某个列名可能会出现在多个表中。好的做法是,如果在SELECT语句中操作多个表,就应使用完全限定列名来避免歧义。
提示:不止一种解决方案
正如这一课前面所述,虽然这里给出的样例代码运行良好,但它并不是解决这种数据检索的最有效方法。在后面两课学习 JOIN 时,我们还会遇到这个例子。
这一课学习了什么是子查询,如何使用它们。子查询常用于WHERE子句的 IN操作符中,以及用来填充计算列。我们举了这两种操作类型的例子。
作者:Rainary 发表于 21:25:38
阅读:46 评论:0
springboot-加载自定义的properties文件
http://blog.csdn.net/liuchuanhong1/article/details/
http://blog.csdn.net/liuchuanhong1/article/details/
liuchuanhong1
在我们的开发中,有很多配置文件是需要分开配置的,例如kafka.properties,amq.properties等,那这些自定义的配置文件,怎么加载到对应的类里面了,下面就来说说这个问题。
在src/main/resources目录下新建一个config文件夹,用来存放我们的properties文件。目录结构如下:
user.properties配置文件内容如下:
com.chhliu.springboot.author=xyy
com.chhliu.springboot.age=${com.chhliu.age}
com.chhliu.springboot.sex=woman
com.chhliu.springboot.time=
com.chhliu.age=27
对应的配置类如下:
public class ConfigProperties {
public String getAuthor() {
public void setAuthor(String author) {
this.author =
public int getAge() {
public void setAge(int age) {
this.age =
public String getSex() {
public void setSex(String sex) {
this.sex =
public String getTime() {
public void setTime(String time) {
this.time =
public String toString() {
return &ConfigProperties [author=& + author + &, age=& + age + &, sex=& + sex + &, time=& + time + &]&;
我们怎么来将配置文件里面对应的属性注入到类中了,方法有二
1、过时方法
1.1 在ConfigProperties类上加上如下注解:
@ConfigurationProperties(locations=&classpath:config/user.properties&, prefix=&com.chhliu.springboot&)
其中locations属性用来指定配置文件的位置,prefix用来指定properties配置文件中的key前缀
1.2 在主类上加入配置支持
@EnableConfigurationProperties(ConfigProperties.class)
这样就可以将properties配置文件中的值注入到类中对应的属性上去了,但是上面的这种方式已经被标注为过时了,在新的版本中是不可用的。
2、替代方法
1.1 在ConfigProperties类上加上如下注解:
@Component// 以组件的方式使用,使用的时候可以直接注入
@ConfigurationProperties(prefix=&com.chhliu.springboot&)// 用来指定properties配置文件中的key前缀
@PropertySource(&classpath:config/user.properties&)// 用来指定配置文件的位置
1.2 关闭配置属性的支持
这一步就是将主类上的@EnableConfigurationProperties这个注解注释调,不让springboot自动配置,使用我们的手动配置
3、测试结果
ConfigProperties [author=xyy, age=27, sex=woman, time=]
从上面的测试结果,可以看出,配置生效了。
作者:liuchuanhong1 发表于 20:43:34
阅读:45 评论:0
《剑指offer》刷题笔记(链表):从尾到头打印链表
http://blog.csdn.net/u/article/details/
http://blog.csdn.net/u/article/details/
《剑指offer》刷题笔记(链表):从尾到头打印链表
转载请注明作者和出处:
代码地址:
文章地址:
刷题平台:
库:剑指offer
者:WordZzzz
链表应该是面试被提及最频繁的数据结构。链表的创建、插入节点、删除结点等操作都只需要20行左右的代码就能实现,其代码量比较适合面试。
在创建链表时,无需知道链表的长度,当插入一个结点时,我们只需要为新结点分配内存,然后调整指针的指向来确保新节点被链接到链表当中。内存分配不是在创建链表时一次性完成,而是没添加一个结点分配一次内存。由于没有闲置的内存,链表的空间效率比数组好。
输入一个链表,从尾到头打印链表每个节点的值。
直接修改输入数据
如果可以修改原来链表的结构,那么把链表中链接结点的指针反转过来,改变链表的方向,然后就可以从头到尾输出了。
但是,打印通常是一个只读操作,我们不希望打印时修改内容,所以就得想别的办法。
后进先出,我们可以用栈实现这种顺序。没经过一个结点的时候,把该节点放到一个栈里面,当遍历完整个链表后,再从栈顶开始逐个输出结点的值,此时输出的结点的顺序已经反转过来了。
递归在本质上就是一个栈结构,于是很自然地又想到了用递归来实现。每访问到一个结点的时候,先递归输出它后面的节点,再输出该节点自身,这样链表的输出结果就反过来了。
C++代码实现
class Solution {
vector&int& printListFromTailToHead(ListNode* head) {
vector&int&
stack&int&
ListNode* pNode =
while(pNode != NULL){
nodes.push(pNode-&val);
pNode = pNode-&
while(!nodes.empty()){
result.push_back(nodes.top());
nodes.pop();
class Solution {
vector&int& printListFromTailToHead(ListNode* head) {
vector&int&
if(head != NULL)
value.insert(value.begin(),head-&val);
if(head-&next != NULL)
vector&int& tempVec = printListFromTailToHead(head-&next);
if(tempVec.size()&0)
value.insert(value.begin(),tempVec.begin(),tempVec.end());
Python代码实现
python的实现依旧是那么简单,一直往列表头放数据就好。
class Solution:
def printListFromTailToHead(self, listNode):
head = listNode
while head:
l.insert(0, head.val)
head = head.next
系列教程持续发布中,欢迎订阅、关注、收藏、评论、点赞哦~~( ̄▽ ̄~)~
完的汪(∪?∪)???zzz
作者:u 发表于 19:56:11
阅读:74 评论:0
面试问题项目已经依赖了一个parent,怎么引入spring boot依赖
http://blog.csdn.net/hxpjava1/article/details/
http://blog.csdn.net/hxpjava1/article/details/
&dependencyManagement&
&dependencies&
&dependency&
&groupId&org.springframework.boot&/groupId&
&artifactId&spring-boot-dependencies&/artifactId&
&version&1.5.7.RELEASE&/version&
&type&pom&/type&
&scope&import&/scope&
&/dependency&
&/dependencyManagement&
这里用的是import &scope
作者:hxpjava1 发表于 19:16:18
阅读:76 评论:0
面试问题a++是线程安全的么
http://blog.csdn.net/hxpjava1/article/details/
http://blog.csdn.net/hxpjava1/article/details/
a++不是线程安全的,因为包含读取,计算,写入三个步骤,不是原子的。
第二问怎么实现++原子
用AutomicIntegeer或AutomicLong的incrementAndGet方法
作者:hxpjava1 发表于 19:06:22
阅读:72 评论:0
Android进阶---Android Webview重定向问题解决
http://blog.csdn.net/dg_summer/article/details/
http://blog.csdn.net/dg_summer/article/details/
项目中需要webview重定向,但是由于一个webveiw里面有许多加载操作,因此在调用webview。goback()方法时,往往达不到我们需要的操作效果。
1.解决方法
WebBackForwardList webBackForwardList=webview.copyBackForwardList()获取webview加载栈,然后更具加载栈做逻辑操作
2.webBackForwardList常用的方法
int size = webBackForwardList.getSize()
webBackForwardList.getCurrentItem()
webBackForwardList.getCurrentIndex()
webBackForwardList.getItemAtIndex(index)
getsize()方法获取当前加载栈的长度;
getCurrentItem()获取当前webview所加载的界面,我们可以在这个方法下获得url,title等内容;
getCurrentIndex()获取当前加载在加载栈中的位置;
webBackForwardList.getItemAtIndex(index)获取加载栈中第index页面;
3.合理使用
在2中我们获取到加载页面的一些信息,然后可以根据当前url,标题,位置。来进行相应的处理。
4.Demo使用
现在我们有这样一个场景:打开一个activity,webview加载A界面,然后用户在A里面点击B,然后点击C,点击D。返回操作时我们需要从D跳到B,然后跳A.下面为代码:
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (webView.canGoBack()) {
WebBackForwardList webBackForwardList = webView.copyBackForwardList();
if (webBackForwardList.getCurrentIndex() == 4) {
webView.loadUrl(webBackForwardList.getItemAtIndex(1).getUrl());
return true;
webView.goBack();
return true;
作者:DG_summer 发表于 18:55:55
阅读:79 评论:0
【后缀数组】不可重叠最长重复子串
http://blog.csdn.net/huangzhengdoc/article/details/
http://blog.csdn.net/huangzhengdoc/article/details/
huangzhengdoc
这题阴森可怕,两个后缀可以不相同?哦天哪,怎么判断呢。
于是,某个聪明的人发现,后缀中两两字符的ANSI值的差是相等的,于是我们可以维护一个由差值组成的后缀数组。所以呢,我们就可以用后缀数组解这道题了,但是这一题,我们还要引入一个新的概念height数组和h数组。
height数组的定义就是排名为 i 与 i-1 的最长公共前缀。
h就是代表排名为 i
的后缀与其前一个后缀的最长前缀
#include&map&
#include&queue&
#include&cmath&
#include&cstdio&
#include&cstdlib&
#include&cstring&
#include&iostream&
#include&algorithm&
#define Maxchar 28192 //2
#define Maxs 30
#define mes(x,y) memset(x,y,sizeof(x));
#define mpy(x,y) memcpy(x,y,sizeof(x))
#define INF
int n,a[Maxchar+1],tt[Maxchar+1],Rank[Maxchar+1],sa1[Maxchar+1],Rank2[Maxchar+1],sa2[Maxchar+1],Rsort[Maxchar+1];
void get_sa(int n,int m){
memcpy(Rank,a,sizeof(Rank));
memset(Rsort,0,sizeof(Rsort));
for(int i=1;i&=n;i++)Rsort[Rank[i]]++;
for(int i=1;i&=m;i++)Rsort[i]+=Rsort[i-1];
for(int i=n;i&=1;i--)sa1[Rsort[Rank[i]]--]=i;
int ln=1,p=0;
while(p&n){
for(int i=n-ln+1;i&=n;i++)sa2[++k]=i;
for(int i=1;i&=n;i++)if(sa1[i]-ln&0)sa2[++k]=sa1[i]-
memset(Rsort,0,sizeof(Rsort));
for(int i=1;i&=n;i++)Rsort[Rank[i]]++;
for(int i=1;i&=m;i++)Rsort[i]+=Rsort[i-1];
for(int i=n;i&=1;i--)sa1[Rsort[Rank[sa2[i]]]--]=sa2[i];
for(int i=1;i&=n;i++)tt[i]=Rank[i];
p=1;Rank[sa1[1]]=1;
for(int i=2;i&=n;i++){
if(tt[sa1[i]]!=tt[sa1[i-1]]||tt[sa1[i]+ln]!=tt[sa1[i-1]+ln])p++;
Rank[sa1[i]]=p;
m=p;ln*=2;
//上面是基础的后缀数组模版。
int height[Maxchar+1];
void get_he(int n){
int j,k=0;
for(int i=2;i&=n;i++){
j=sa1[Rank[i]-1];
if(k!=0)k--;
while(a[j+k]==a[i+k])k++;//匹配最初前缀
//h数组的定义就是后缀 i 和后缀 i-1的最长前缀
height[Rank[i]]=k;//记录两个后缀的最长前缀
//最后记录下排名为 i 的后缀与其前一个后缀的最长前缀
//就是新的h数组,这个才是后缀数组的真谛。
bool check(int k,int n){
for(int i=2;i&=n;i++){
if(height[i]&=k){
for(int j=i-1;j&=2;j--){
if(abs(sa1[i]-sa1[j])&=k)//满足直接true
if(height[j]&k)//二分假如现在条件不满足就跳出
int main(){
while(scanf("%d",&n)!=EOF){
for(int i=1;i&=n;i++)scanf("%d",&a[i]);
int mmax=-9999999;
for(int i=1;i&n;i++){
a[i]=a[i+1]-a[i]+88;
if(mmax&a[i])mmax=a[i];
//取maxx是为了减少后缀数组的基数排序时间复杂度
a[n]=0;n--;
get_sa(n,mmax);get_he(n);
//然后通过二分枚举答案
int l=1,r=n,ans=1;
while(l&=r){
int mid=(l+r)/2;
if(check(mid,n)==true){//二分枚举长度
else r=mid-1;
if(ans&4)printf("0\n");
else printf("%d\n",ans+1);
&查看原文:
作者:huangzhengdoc 发表于 18:42:31
阅读:48 评论:0
面试问题spring boot自动配置是怎么实现的
http://blog.csdn.net/hxpjava1/article/details/
http://blog.csdn.net/hxpjava1/article/details/
之前一直在用SpringBoot框架,一直感觉SpringBoot框架自动配置的功能很强大,但是并没有明白它是怎么实现自动配置的,现在有空研究了一下,大概明白了SpringBoot框架是怎么实现自动配置的功能,我们编写一个最简单的自动配置功能,大概的总结一下.
一,配置属性类
其实就是值对象注入的方式去配置一些Spring常用的配置,我们编写一个最简单的配置对象。
@ConfigurationProperties(prefix = &hello&)
//@Component //如果这里添加了注解那么在自动配置类的时候就不用添加@enableConfigurationProperties(HelloProperties.class)注解.
public class HelloProperties {
private String msg=&default&;//现在我们在配置文件写hello.msg=world,因为简单就不再展示;如果那么默认为default.
public String getMsg() {
public void setMsg(String msg) {
this.msg =
这是一个简单的属性值对象,那么相当于写死的字段就是SpringBoot为我们自动配置的配置,那么我们很多时候可以自己在application.properties中修改某些配置就是这样的道理,我们不设置就是默认的,设置了就是我们设置的属性。
二,自动配置类
上面已经构建了我们简单的属性对象,那么现在我们要通过属性对象得到相应的属性值将其注入到我们的Bean中,这些Bean也就是一些SpringBoot启动后为我们自动配置生成的Bean,当然SpringBoot优先使用我们配置的Bean这个功能是如何实现的,我们往下看一下就明白了。
首先我们需要一个功能Bean,可以把这个Bean看做是SpringBoot框架启动后在容器里面生成的为我们服务的内置Bean,简单的写一个。
//@Component
这里很重要,如果我们添加了这个注解那么,按照我们下面的设置SpringBoot会优先使用我们配置的这个Bean,这是符合SpringBoot框架优先使用自定义Bean的原则的。
public class HelloService {
private String msg = &service&;//如果自动配置没有读入成功,那么为默认值
public String say() {
return &hello & +
}//为我们服务的方法
public String getMsg() {
public void setMsg(String msg) {
this.msg =
现在编写我们的自动配置类。
@Configuration //配置类
@EnableConfigurationProperties(HelloProperties.class)//这里就是前面说的,这个注解读入我们的配置对象类
@ConditionalOnClass(HelloService.class)//当类路径存在这个类时才会加载这个配置类,否则跳过,这个很有用比如不同jar包间类依赖,依赖的类不存在直接跳过,不会报错public class HelloAutoConfiguration {
@Autowired
private HelloProperties helloP
@ConditionalOnMissingBean(HelloService.class)//这个配置就是SpringBoot可以优先使用自定义Bean的核心所在,如果没有我们的自定义Bean那么才会自动配置一个新的Bean
public HelloService auto(){
HelloService helloService =new HelloService();
helloService.setMsg(helloProperties.getMsg());
return helloS
好了现在自动配置的类也写好了,我们可以启动一下SpringBoot应用,测试一下。
三,测试自动配置
@SpringBootApplication
@RestController
public class MyRun {
@Autowired
private HelloService helloS
@RequestMapping(&/auto/home&)
public String home(){
return helloService.say();
public static void main(String[] args) {
SpringApplication.run(MyRun.class,args);
ok ,运行后访问你会看到:
hello world
代表我们的自动配置功能成功。
四,SpringBoot管理自动配置
其实在很多时候我们的配置是在很多jar包里的,那么我们新的应用该怎么读入这些jar包里的配置文件呢,SpringBoot是这样管理的。
最主要的注解就是@enableAutoConfiguration,而这个注解会导入一个EnableAutoConfigurationImportSelector的类,而这个类会去读取一个spring.factories下key为EnableAutoConfiguration全限定名对应值.
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework..ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.hornetq.HornetQAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,\
org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,\
org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,\
org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.velocity.VelocityAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
所以如果需要我们可以在我们的resources目录下创建spring.factories下添加类似的配置即可。。
ok,自动配置的原理差不多就这样,我现在了解的并不深入,还需要继续学习。
作者:hxpjava1 发表于 18:12:44
阅读:72 评论:0
关于创建趣味编程文章列表的倡议和通告
http://blog.csdn.net/number1killer/article/details/
http://blog.csdn.net/number1killer/article/details/
number1killer
作者:number1killer 发表于 18:03:19
阅读:65 评论:0
面试问题new Integer(10)和new Integer(10)是否相等,new Integer(300)和new Integer(300)是否相等
http://blog.csdn.net/hxpjava1/article/details/
http://blog.csdn.net/hxpjava1/article/details/
本文将介绍一下Java中关于Integer的缓存知识,首先看一下下面的代码,猜测一下会输出什么结果。
对于上述代码,由于运用的是“==”,而java中“==”比较的是两个引用而非引用的值,所以大家普遍认为两个输出都会是false,然而运行结果则为true,false。
Java中关于Integer缓存机制的介绍:
由于上述代码进行了自动装包操作,查看Java的Integer源码的valueOf(int)代码如下:
由上述源码可知,当装包对象在IntegerCache.low到Integer.high之间时,结果直接从IntegerCache中获取,否则直接创造一个实例。下面为IntegerCache的源码:
分析上述源码可知,IntegerCache的low为-128,而high可以通过&-XX:AutoBoxCacheMax=&size&&指定,默认的high为127。当设置high之后,high的实际值取默认值和设置值中最大值,同时小于或等于0X7FFFFF7E。然后将low到high之间的数值存放到cache中。由于该类及方法都是静态的,因此在首次使用时会执行该操作,当需要对low到high之间的数字进行装包操作时,则直接返回IntegerCache.cache中现成的引用。所以上述对基本类型3进行装包时返回同一个引用,故结果输出true。
当然,Java中除了对Integer有缓存机制外,其中还有ByteCache,ShortCache,LongCache,CharacterCache分别对其对应的类型进行缓存,其中Byte,Short,Long的缓存范围都为-128——127,Character为0——127。特别要注意的是这几个缓存中,只有Integer的缓存上限(high)可以设置,其他的都不能进行设置,为固定范围。
作者:hxpjava1 发表于 18:00:04
阅读:72 评论:0
面试问题a+=b 和a=a+b的区别
http://blog.csdn.net/hxpjava1/article/details/
http://blog.csdn.net/hxpjava1/article/details/
在Java语言中a+=b和a=a+b是有区别的,主要的区别是在运算时精度的问题,当然了-=、*=、/=,%=也都是一个道理。这里以a+=b和a=a+b为例做说明。
&&&&&&&& (1)下面以一段Java程序为例,试一试a+=b的形式:
public&classDemo
&&&&public&static&void&
main(String[] args)
&&&&&&&&short&a=4;
&&&&&&& a+=5;
&&&&&&& System.out.println(a);
可以看出这段程序的结果是9,程序没有问题的。需要明确的是“+=”这个运算符在Java中是一个运算符,而不是两个,程序在执行“+=”时,会自动向高精度进行数据类型转换。所以上面的程序在执行时编译器没有报错。
(2)下面试一试a=a+b的形式:
public&classDemo
&&&&public&static&void&
main(String[] args)
&&&&&&&&short&a=4;
&&&&&&& a=a+5;
&&&&&&& System.out.println(a);
可以从截图中看出在使用a=a+b的形式时出现了问题,因为a是short类型的变量,而5默认为int类型的变量,short类型+int类型结果肯定会自动转换成int类型啦,
此时就存在数据类型不一致的问题,用short类型的变量去保存int类型的变量编译器当然会报错了,就好比你用装一两水的杯子去装二两水,
当然是装不下的,如果你非要用装一两水的杯子去装二两水,肯定可以硬到进去,但是肯定会洒掉一部分水。所以如果这里非要用short类型的变量去装int类型的数据,可以用强制转换,确定是会丢失精度。
以下是强制转换后的结果:
public&classDemo
&&&&public&static&void&main(String[]
&&&&&&&&short&a=4;
&&&&&&& a=(short)(a+5);
&&&&&&& System.out.println(a);
(3)总结一句,这两种形式的主要区别在于是否进行数据类型的自动转换,当两个操作数同类型时这两种形式的运算结果是没有差别的,当两个操作数数据类型不同时,
且左操作数即保存结果的操作数的数据精度要低,此时这两种形式才有区别。
作者:hxpjava1 发表于 17:55:53
阅读:171 评论:0
面试问题组合和聚合有什么区别
http://blog.csdn.net/hxpjava1/article/details/
http://blog.csdn.net/hxpjava1/article/details/
大家都知道UML的类图中一般包含五种关系即 &关联&聚合&组合&泛化 依赖 &有些人可能会感觉组合跟聚合有点难区分 说难其实是相对其他几种关系而言 实际上想分清这两种关系一点也不难&
聚合跟组合其实都属于关联 只不过它们是两种特殊的关联 因为本是同根生 所以它们之间难免会有相似之处 下面让我们一起来看一下它们之间有何不同
聚合与组合的概念相信不用我在此赘述大家就已经了解了 下面直接上例子
程老师的《大话》里举大那个大雁的例子很贴切 在此我就借用一下 大雁喜欢热闹害怕孤独 所以它们一直过着群居的生活 这样就有了雁群 每一只大雁都有自己的雁群 每个雁群都有好多大雁 大雁与雁群的这种关系就可以称之为聚合 另外每只大雁都有两只翅膀 大雁与雁翅的关系就叫做组合 有此可见 聚合的关系明显没有组合紧密 大雁不会因为它们的群主将雁群解散而无法生存 而雁翅就无法脱离大雁而单独生存——组合关系的类具有相同的生命周期
聚合关系图:
组合关系图:
从从代码上看这两种关系的区别在于:
构造函数不同
[csharp]&&
[csharp]&&
聚合关系的类里含有另一个类作为参数
雁群类(GooseGroup)的构造函数中要用到大雁(Goose)作为参数把值传进来 大雁类(Goose)可以脱离雁群类而独立存在&
组合关系的类里含有另一个类的实例化
大雁类(Goose)在实例化之前 一定要先实例化翅膀类(Wings) 两个类紧密耦合在一起 它们有相同的生命周期 翅膀类(Wings)不可以脱离大雁类(Goose)而独立存在
信息的封装性不同
在聚合关系中,客户端可以同时了解雁群类和大雁类,因为他们都是独立的
而在组合关系中,客户端只认识大雁类,根本就不知道翅膀类的存在,因为翅膀类被严密的封装在大雁类中。
作者:hxpjava1 发表于 17:51:43
阅读:87 评论:0
Linux文件系统详解
http://blog.csdn.net/zengxiantao1994/article/details/
http://blog.csdn.net/zengxiantao1994/article/details/
zengxiantao1994
一、Linux文件系统
& & & & 在Linux中,所有的设备都是文件。文件的类型是根据文件头字段来判断,而非文件的后缀名。
& & & &&用户配置文件:~/.bashrc&&~/.bash_profile&&~/.bash_logout
& & & &&全局配置文件:/etc/profile&&/etc/bashrc
二、Linux文件系统目录结构
& & & &&linux的文件系统是采用级层式的树状目录结构,在此结构中的最上层是根目录“/”,然后在此目录下再创建其他的目录。深刻理解linux文件目录是非常重要的。
& & & &&linux下的根目录中重要的目录如下是系统自动分配的:root目录、home目录、bin目录、sbin目录、mnt目录、etc目录、var目录、boot目录、usr目录、tmp目录(均为同级目录)。
& & & &&/:系统根目录。
& & & &&root目录:用于存放root用户相关文件的目录
& & & &&home目录:用于存放普通用户的相关文件的目录
& & & &&bin目录:用于存放常用命令的目录
& & & &&sbin目录:用于存放要具有一定权限才可以使用的命令的目录
& & & &&mnt目录:用于默认挂载软驱、光驱的目录
& & & &&etc目录:用于存放配置相关的文件的目录
& & & &&var目录:用于存放经常变化的文件的目录
& & & &&boot目录:用于存放系统引导文件的目录(重要)
& & & &&usr目录:用于存放安装的默认目录(安装文件会默认安装在usr目录里)
& & & &&/usr/doc& /usr/share/doc:帮助文档
& & & &&/usr/share:共享文件和数据
& & & &&/usr/bin:几乎所有的命令程序
& & & &&/usr/sbin:系统管理的命令
& & & &&/usr/include:C语言头文件
& & & &&/usr/lib:库文件和数据文件
& & & &&/usr/local:本地安装的软件
& & & &&/usr/src:Linux源代码
& & & &&tmp目录:用于存入临时文件的目录
& & & &&cd /返回到主目录下。ls与dir功能相同,列出当前目录下的所有文件名。pwd命令显示当前在哪个路径下面。
& & & &&当前目录:pwd命令可以显示当前目录。
& & & &&相对路径:以当前目录开始寻找目标文件或文件夹 . .. ~。
& & & &&绝对路径:以根目录开始寻找目录文件或文件夹 /目录。
& & & &&工作目录:就是执行文件所在的目录。
三、挂载文件系统
& & & &&挂载是指将一个硬件设备(例如硬盘、U盘、光盘等)对应到一个已存在的目录上。若要访问设备中的文件,必须将文件挂载到一个已存在的目录上,然后通过访问这个目录来访问存储设备。
& & & &&注意:挂载目录可以不为空,但挂载后这个目录下以前的内容将不可用。
& & & &&可以通过mount命令来挂载文件系统,语法为:
& & & &&mount &-t &file_system_type&device_to_mount &directory_to_mount_to
& & & &&例如:$ mount -t iso9660/dev/cdrom /mnt/cdrom
& & & &&将 CD-ROM 挂载到 /mnt/cdrom 目录。
& & & &&注意:file_system_type用来指定文件系统类型,通常可以不指定,Linux会自动正确选择文件系统类型。
& & & &&可以通过umount命令来卸载文件系统。例如,卸载cdrom:$ umount /dev/cdrom
& & & &&不过,大部分现代的Linux系统都有自动挂载卸载功能,unmount 命令较少用到。
四、文件操作常用命令
& & & &&1、toucha.txt
& & & &&如果a.txt不存在,生成一个新的空文档a.txt。如果a.txt存在,那么只更改该文档的时间信息。
& & & &&2、ls
& & & &&是list的简写,列出当前目录下的所有文件名ls -l a.txt列出文件的详细信息,ls –a会显示当前目录下所有文件(包括隐藏文件)。
& & & &&3、cp&
a.txt&b.txt
& & & &&cp是copy的简写,用来复制文件。在工作目录下,将a.txt复制到文件b.txtcp a.txt ..:将a.txt复制到父目录的a.txt。
& & & &&4、mva.txt
& & & &&mv是move的简写,用来移动文件。将a.txt移动成为c.txt (相当于重命名rename)。mv &c.txt &/home/vamei:将c.txt移动到/home/vamei目录。
& & & &&5、rma.txt
& & & &&rm是remove的缩写,用于删除文件。删除a.txt。rm -r /home/vamei
:删除从/home/vamei向下的整个子文件系统。-r表示recursive,是指重复删除的操作,/home/vamei文件夹为空,然后删除/home/vamei文件夹本身。($rm -rf /:它会删除整个文件树。f的目的是告诉rm放心干,不用再确认了…… 一般情况下,应该没有人会用这个命令。)
& & & &&6、mkdir&
/home/vamei/good:创建一个新的目录。
& & & &&7、rmdir& /home/vamei/good:删除一个空的目录。
& & & &&8、pwd:显示当前工作目录。
& & & &&9、cd[dirName]
& & & &&改变目录至dirName。其中dirName可为绝对路径或相对路径。若目录命令省略,则变换至使用者登录时所在的目录(Home directory)。另外,“~”也表示为Home目录的意思,“.”则是表示当前所在的目录,“..”则表示当前目录位置的上一层目录。
& & & &&10、ln
& & & &&命令ln:建立符号连接,ln –s 源目标。ln -s /etc/inittab inittab [inittab指向实际文件/etc/inittab]。
五、Linux文件名通配符表达式
& & & &&(wild card, 也叫filename pattern matching)之前所讲的命令,比如ls, mv, cp都可以接收多个参数,比如:
& & & &&ls -l a.txt b.txt c.txt:就可以列出这三个文件的所有信息。有时候,我们想列出工作目录下所有的以.txt结尾的文件的信息,可以用下面的方式:ls
-l *.txt。
& & & &&*.txt的写法就运用了Linux通配表达式。它与正则表达式相类似,但语法有所不同。
Filename Pattern Matching
任意多个任意字符
任意一个字符
字符k或者字符l
数字0到4字符中的一个
b到e字符中的一个
一个字符,这个字符不是m,n,p
& & & &&Linux会找到符合表达式的文件名,然后用这些文件名作为参数传递给命令。注意,当使用rm的时候,要格外小心。下面两个命令,只相差一个空格,但效果大为不同:
& & & &&rm * .txt&&&&rm *.txt:前一个命令会删除当前目录下所有文件!
六、Linux文件权限
& & & &&1、chmod 755a.txt:(必须是文件a.txt的拥有者才能运行此命令。或者以$sudo
chmod 755 a.txt的方式,以超级用户的身份运行该命令。)
& & & &&change mode改变a.txt的读、写以及执行权限。每个文件都有九位的读写执行权限,分为三组,分别对应拥有者(owner),拥有组(owner group)中的用户和所有其他用户(other)。在这里,我们也有三个数字,755,对应三个组。7被分配给拥有者,5被分配给拥有组,最后一个5分配给其它用户。Linux规定:4为有读取的权利(r),2为有写入的权利(w),1为有执行的权利(x)。我们看到的7实际上是4
+ 2 + 1,表示拥有者有读、写、执行三项权利。
& & & &&这时,运行$ls -l a.txt, 应该看到九位的权限变成了rwxr-xr-x。根据自己的需要,你可以用比如444, 744代替755,来让文件有不同的权限。
& & & &&- rw- r-- r--
& & & &&-为文件类型,-为普通文件,d为文件夹,
& & & &&rw-文件的所有者对该文件的权限。r--文件所在组对该文件的权限。r--其它组的用户对该文件的权限。
& & & &&注:修改文件访问权限只有root用户和文件所有者。查看当前操作人员命令who am i。
& & & &&chmod 777 用户名
& & & &&解释:- --- --- --- &000&&& &&&- r-- r-- r— 444 &&&&&- rw- rw- rw- &666
& & & &&& & & &&&
& & &&- rwx rwx rwx &&777&&&&&&&&& - rwx rw- r-- &764
& & & &&2、sudo
chownroot a.txt
& & & &&changeowner改变文件的拥有者为root用户。这个命令需要有超级用户权限才能执行,所以我们在命令之前加上sudo。
& & & &&3、sudo
chgrp root a.txt
& & & &&change group 改变文件的拥有组为root组。
作者:zengxiantao1994 发表于 17:47:31
阅读:64 评论:0
解答,修正(JAVA+=运算程序诡异事件 )
http://blog.csdn.net/number1killer/article/details/
http://blog.csdn.net/number1killer/article/details/
number1killer
作者:number1killer 发表于 17:03:22
阅读:125 评论:0
linux学习---linux命令大全
http://blog.csdn.net/xiaoxiaopengbo/article/details/
http://blog.csdn.net/xiaoxiaopengbo/article/details/
XiaoXiaoPengBo
一.管理文件和目录1.1 pwd命令该命令的英文解释为print working directory(打印工作目录)。输入pwd命令,Linux会输出当前目录。1.2 cd命令cd命令用来改变所在目录。cd /&&&&& 转到根目录中 cd ~&&&& 转到/home/user用户目录下 cd /usr 转到根目录下的usr目录中-------------绝对路径 cd test 转到当前目录下的test子目录中-------相对路径1.3 ls命令ls命令用来查看目录的内容。1.4 cat命令cat命令可以用来合并文件,也可以用来在屏幕上显示整个文件的内容。cat snow.txt 该命令显示文件snow.txt的内容,ctrl+D退出cat。1.5 grep命令grep命令的最大功能是在一堆文件中查找一个特定的字符串。grep money test.txt 以上命令在test.txt中查找money这个字符串,grep查找是区分大小写的。通常此部分可以和管道一起使用ps |grep bash 管道:把一个命令的输出当成文件交给右边的命令处理1.6 touch命令touch命令用来创建新文件,他可以创建一个空白的文件,可以在其中添加文本和数据。touch newfile 该命令创建一个名为newfile的空白文件。1.7 cp命令cp命令用来拷贝文件,要复制文件,输入命令:cp &source filename& &target filename&cp t.txt Document/t&&& 该命令将把文件t.txt复制到Document目录下,并命名为t。1.8 mv命令mv命令用来移动文件。mv t.txt Document&&& 把文件t.txt 移动到目录Document中。1.9 rm命令rm命令用来删除文件。rm t.txt&& 该命令删除文件t.txt1.10 rmdir命令rmdir命令用来删除目录。补充:1.11 mkdir命令mkdir用来创建目录&二.有关磁盘空间的命令2.1 mount命令mount命令的功能是挂载文件系统,可以挂载硬盘、光盘、软盘,也可以挂载NFS网络文件系统。这个命令的标准用法如下:mount –t 设备类型存放目录 mount IP地址:/所提供的目录存放目录在目录/mnt下,挂上iso9660文件系统。输入命令:mount –t iso9660 /dev/hdb /cdrom2.2 umount命令umount命令的功能是卸载已挂上的文件系统,在关闭系统前应该把所有挂载上的文件系统卸载。这个命令和mount命令是相对的。用法:umount 已挂上的目录或设备卸载已挂上的/cdrom目录,输入命令:umount /cdrom卸载已挂上的某个分区,输入命令:umount /dev/hdb12.3 df命令df命令用来检查硬盘分区和已挂在的文件系统的磁盘空间,也就是说,检查硬盘的使用量。标准用法如下:df [-选项]例如,要列出全部文件系统和各分区的磁盘使用情况,输入命令:df –a2.4 du命令du命令的功能是用于显示文件目录或大小。标准用法:du [-选项]2.5 fsck命令fsck命令的功能是检查和修复Linux文件系统,这个命令最好在没有人或是没有分区挂上来时使用,其实每次开机系统都会做一次检查,看是否有坏轨或数据流失的现象。用法:fsck (-选项) 分区名称三.文件备份和压缩命令3.1 bzip2命令要使用bzip2来压缩文件,在shell提示下输入命令:bzip2 filename文件即会被压缩,并被保存为filename.bz2。要解压缩文件,输入命令:bunzip2 filename.bz2filename.bz2会被删除,而以filename代替。bzip2 filename.bz2 file1 file2 file3 /usr/work/school上面的命令把file1、file2、file3以及/usr/work/school目录中的内容压缩起来放入filename.bz2。3.2 gzip命令要使用gzip来压缩文件,输入命令:gzip filename文件即会被压缩,并被保存为filename.gz。要解压缩文件,输入命令:gunzip filename.gzfilename.gz会被删除,而以filename代替。gzip -r filename.gz file1 file2 file3 /usr/work/school上面的命令把file1、file2、file3以及/usr/work/school目录中的内容压缩起来放入filename.gz。3.3 zip命令zip命令的使用方法同gzip。3.4 tar命令tar命令最早是用来做磁带备份的,但是由于硬盘容量越来越大,因此现在主要用这个命令来备份所有的文件。tar这个命令把大量的文件和目录打包成一个文件。要创建一个tar文件,输入命令:tar –cvf filename.tar directory/file /home/mine上面的命令将directory/file、/home/mine放入归档文件中。要列出tar文件的内容,输入命令:tar –tvf filename.tar要抽取tar文件的命令,输入命令:tar –xvf filename.tar这个命令不会删除tar文件,但会把解除归档的内容复制到当前工作目录下,并保留归档文件所使用的任何目录结构。请记住,tar默认不压缩文件。要创建一个使用tar和bzip2来归档压缩的文件,使用-j选项:tar –cjvf filename.tbz file如果使用bunzip2命令解压filename.tbz文件,则filename.tbz会被删除,以filename.tar代替。要扩展并解除归档bzip tar文件,输入命令:tar –xjvf filename.tbz要创建一个用tar和gzip归档并压缩的文件,使用-z选项:tar –czvf filename.tgz file如果使用gunzip命令解压filename.tgz文件,则filename.tgz会被删除,以filename.tar代替。四.有关关机和查看系统信息的命令4.1 shutdown命令要使用这个命令必须保证是根用户,否则使用su命令改变为根用户。命令格式如下:shutdown –(选项)加入要在2min内关机,输入命令:shutdown –t 2如果是关机后重启,输入命令:shutdown –r4.2 reboot命令这个命令也是一个关机命令,只有输入,不加任何参数,系统会以最快的速度关机,且不将内存或缓冲区里的东西写回硬盘。4.3 ps命令ps命令用来查看在计算机系统中有哪些程序正在执行,及其执行的情况。这是一个相当强大的命令,可以用它来找出所有的process id和名称。另外,ps命令也可以用来列出所有程序占用内存的情况。用法如下:ps –(选项)详细参考:http://blog.csdn.net/xiaoxiaopengbo/article/details/4.4 top命令top命令可以查看目前程序的执行情景和内存使用。它和ps类似,不过,它会几秒钟更新一次系统状态,方便追踪。要离开这个程序,按Ctrl+C键就可以了。4.5 kill命令kill命令用来终止一个正在执行中的进程。如果一个程序执行过程中失败了,可以把这个程序终止,避免留在内存中占用系统资源。不过,它的实际意义是送一个信号给这个正在执行的程序,叫它自杀。可以送很多信号给这些程序,也可以让他们受到信号后做很多事情。标准用法:kill –(选项) pid在执行kill命令前。可以先用ps命令查一下某宕掉程序的pid,然后使用kill除去某个程序。例如,终止pid为90的程序:kill 90将 pid 为 323 的行程砍掉 (kill) :kill -9 323将 pid 为 456 的行程重跑(restart) :kill -HUP 4564.6 date命令date命令用来显示、设定和修改现在的时间和日期。标准用法:date –(选项) 显示时间格式(以+号开头,后加格式) date 设定时间格式如果输入命令:date “+%x,%r”系统返回如下信息:2010年3月26日,下午 18时06分49秒4.7 cal命令cal命令有两种功能:显示月历以及年历。直接输入cal命令则系统会显示目前月份的月历。若要显示一整年的年历,可以在cal命令后加4位数的公元年份。例如要显示2008年的年历,必须输入:cal 2008若输入 cal 08 ,则最显示公元8年的年历。若只需要查看某一年份中某一月份的月历,可以输入:cal 月份公元年份。例如输入:&cal 12 2004”。五.管理使用者和设立权限的命令5.1 chmod命令chmod命令用来改变许可权限。读取、写入和执行是许可权限中的三个主要设置。因为用户在他们的账号被创建时就被编入一个组群,所以还可以指定那些组群可以读取、写入或执行某一文件。其中:r—文件可以被读取 w—文件可以被写入 x—文件可以被执行,如果文件是程序的话可以使用带有-l的ls命令来仔细查看一个文件的许多细节。chmod命令用来设定文件的权限。标准用法:chmod 文件的使用者(u,g,o,a)增减(+,-,=)权限名称(r,w,x) 文件删除某一文件的所有权限,输入命令:chmod a-rwx test.txt为文件所有者添加权限,输入命令:chmod u+rwx test还可以用数字表示权限:4——读取,2——写入,1——执行。下面的两个命令等价:chmod 751 filename chmod u+rwx,g=rx,0=x filename5.2 su命令su命令用来修改用户。这个命令非常重要,它可以让一个普通的使用者拥有超级用户或其他使用者的权限。不过,这个命令必须具有超级用户或其他使用者的口令才能成为超级用户或其他使用者。如果要离开,可以输入exit。标准用法:su 用户名& (如果没有输入用户名则预设为root)举例说明,假设当前用户user01,想要转变为user02,则输入命令:su user02系统返回:password:此时,输入user02的指令,就会变为user02。5.3 useradd命令useradd命令用来增加用户,只有根用户才能增加用户。如果没有登录为根用户,输入su,再输入根口令即可。要增加用户,输入命令:useradd 用户名然后,根据提示为新用户输入一个口令即可。六.线上查询的命令6.1 man命令man命令用来查询和解释一个命令的使用方法和这个命令的注意事项。这个查询查询在每个Linux上都有。通常,使用者只要输入命令man和这个命令的名称shell就会列出一份完整的说明。标准用法:man 命令的名称要查询ls命令的说明书页,输入命令:man ls要翻阅说明书页,可以使用Page Up和Page Down键,或使用空格键向后翻一页,使用b向前翻。要退出说明书页,输入命令q。要在说明书页中搜索关键字,输入命令/和要搜索的关键字或短语,然后按Enter键即可。所有出现在说明书页中的关键字都会被突出显示,允许快速地阅读上下文中的关键字。6.2 locate命令locate命令的主要功能是定位文件和目录。有时候,只知道某一文件或目录存在,却不知道在哪儿,就可以用locate来定位文件和目录。使用locate命令,将会看到每一个包括搜索田间的文件和目录。例如,如果想要搜索带有test的这个词的文件,输入命令:locate testlocate命令使用数据库来定位带有test这个词的文件或目录。6.3 whatis命令whatis命令用来查询某个命令的含义。用法简单,也不需要什么参数,直接在whatis命令后加上所要查询的命令就可以了,但是却很实用。要查询mv命令的含义,输入命令:whatis mv七.文件阅读的命令7.1 head命令head命令可以用来查看文件的开头部分。此命令的格式是:head 文件名默认设置,它只查看文件的前10行。但可以通过指定一个数字选项来改变要显示的行数,命令如下:head –20 文件名这个命令将会查看文件的前20行。7.2 tail命令tail命令和head命令恰恰相反。使用tail命令,可以查看文件结尾的10行。这有助于查看日志文件的最后10行来阅读重要的系统信息。还可以使用tail观察日志文件更新的过程。使用-f选项,tail会自动实时地把打开文件中的新信息显示到屏幕上。例如,要活跃地观察/var/log/messages,以根用户身份在shell下输入以下命令:tail –f /var/log/messages7.3 less命令less命令与more命令相似。7.4 more命令more和less的主要区别是,less允许使用箭头来前后移动,而more使用空格键和b键来前后移动。使用ls和more来列举/etc目录下的内容:ls –al /etc | more要使用more在文本文件中搜索关键字,按/键并输入命令搜索条目:/foo使用空格键来先前翻阅页码。按q键退出。more命令标准格式为:more [选项] [fileNames]例如:more -s testfile 逐页显示testfile之档案内容,如有连续两行以上空白行则以一行空白行显示。& more +20 testfile 从第20行开始显示testfile之档案内容。八.网络操作命令8.1 ftp命令ftp命令用来传输文件,非常重要。如果在网络上看到一个很重要的文件,就可以用这个命令把那个文件传到自己的机器上来。标准用法:ftp (-选项) 主机名称或IP地址举例说明,用ftp登录主机,输入命令:ftp 注意:用户必须有相应的存取权限,否则不能从远程系统中获得文件或向远程系统中传输文件。为了使用ftp来传输文件,用户必须知道远程计算机上的合法用户名和口令。8.2 bye命令在ftp模式下,输入bye即可中断目前的连线作业,并结束ftp的执行,没有选项。8.3 ping命令执行ping命令,它会使用ICMP传输协议,发出要求回应的信息,若远程主机的网络没有什么问题,就会回应信息,因而得知该主机运作正常。标准用法:ping (-选项) 主机名称或IP地址举例说明,检测des.bllod.net主机网络功能是否正常,送出去要去信息需完成5次回应,每次间隔10s,数据包的大小为512B,输入命令:ping –c 5 –i 10 –s 504 –t 64 des.blood.net8.4 telnet命令telnet命令的主要功能是进行远程登录。该命令允许用户在使用telnet协议的远程计算机之间进行通信,用户可以通过网络在远程计算机上登录,就像登录到本地机上执行命令一样。为了通过telnet登录计算机,必须知道远程计算机上的合法用户名和口令。telnet只为普通终端提供终端仿真,而不支持X Window等图形环境。标准用法:telnet 主机名或IP例如登录IP地址为140.114.63.12的计算机,输入命令:telnet 140.114.63.12一旦telnet成功连接到远程系统上,就显示登录信息,并提示用户输入用户名和口令。如果用户名和口令正确,就能成功登录并在远程系统上工作。用户结束了远程会话后,一定要确保使用logout命令退出远程系统。然后telnet报告远程会话被关闭,并返回到用户本地机的shell提示符下。8.5 rlogin命令rlogin也是用来远程登录的。它的英文含义是remote login。该命令与telnet命令很相似,允许用户启动远程系统上的交互命令会话。用法:rlogin (-选项) host例如,要登入别人的计算机。输入命令:rlogin –l inin 140.114.125.248.6 netstat命令netstat命令的主要功能是了解Linux系统的网络情况。假设没有指定任何参数给netstat命令,则效果和指定-F参数相同。用法:netstat (-选项)九.定位、查找文件的命令which语法which command说明依序从path环境变量所列的目录中找出command的位置,并显示完整路径的名称。在找到第一个符合条件的程序文件时,就立刻停止搜索,省略其余未搜索目录。范例,找出ls命令的程序文件的位置:which ls系统输出:/usr/bin/lswhereis语法whereis [option] name说明找出特定程序的可执行文件、源代码文件以及manpage的路径。你所提供的name会被先除去前置的路径以及任何.ext形式的扩展名。whereis 只会在标准的Linux目录中进行搜索。常用选项-b只搜索可执行文件。-m只搜索manpage。-s只搜索源代码文件。-B directory更改或限定搜索可执行的文件的目录。-M directory更改或限定搜索manpage的目录。-S directory更改或限定搜索源代码文件的目录。find语法find paths expression [action]说明以paths为搜索起点逐层往下找出每一个符合expression条件的文件,并对该文件执行action所代表的动作。expression是搜索条件,它由一个代表匹配项目的选项以及一个代表匹配模式的参数构成。action是处理动作,它有一个代表“处理方式”的选项以及一个操作参数构成。若不指定action,则默认动作是显示出文件名。常用的搜索条件-name pattern -path pattern -lname pattern找出名称、路径名称或符号链接的目标匹配pattern模式的文件。pattern可以包含shell的文件名通配符,路径是相对于搜索起点的。常见处理动作-print显示出文件的相对路径(相对于搜索起点)。-exec cmd /;执行指定的shell命令。若cmd含有任何shell特殊字符,则他们之前都必须加上/符号,以免shell立刻执行他们。在cmd里,可以用”{}”符号(包括双引号)表示find所找出的文件。locate语法locate patterns说明第一次执行locate时,它会建立一个索引数据库,当往后再次执行时,它便从索引数据库中迅速找出文件的位置。locate很适合用来反复搜索很少变动的目录树,但是对于刚改名的旧文件以及新建的文件,locate就找不到了,除非重建数据库。updatedb语法updatedb [option]说明更新slocate的索引数据库。选项-e directories略过directories所列的目录。十.其他命令9.1 echo命令echo命令用来在显示器上输出一段文字,这个命令常用来输出一些提示信息,因此这个命令的意义在于输出一些文字。它的用法也很简单:echo –(参数) 字串 (可以用&”,也可以不用,显示略有区别)参数n代表输出文字后不换行,如果不加参数会自动换行。输入命令:echo “welcome&& to&& use&& Linux”输出结果为:welcome&& to&& use&& Linux如果不加&”,则输出结果为:welcome to use Linux它们的区别在于后一个输出,每两个输出之间只隔一个空格,这是因为echo把这些输出看做字串的缘故。9.2 clear命令clear命令的主要功能是清除显示器,这个命令很简单,只要输入clear即可。9.3 passwd命令passwd命令用来修改用户的密码。在shell下输入passwd然后,根据提示输入旧密码和新密码即可。9.4 lpr命令lpr命令的功能是把指定的文件发送到打印队列中。例如,lpr foo.txt 会打印 foo.txt 文件。标准用法:lpr filename要查看在打印队列中等待的作业,在命令行中输入命令lpq。系统返回如下信息:active root 389 foo.txt在这个例子中,389是作业号码。还可以取消打印队列中的作业,格式是:lprm作业号码输入命令:lprm 389这样就去修了 foo.txt打印作业。9.5 exit命令退出当前的shell,如果是最后一个shell,那么会退出终端十一.VI使用参照:十二.GCC使用http://blog.csdn.net/xiaoxiaopengbo/article/details/
作者:XiaoXiaoPengBo 发表于 16:30:50
阅读:145 评论:0
一位资深程序员大牛给予Java初学者的学习路线建议
http://blog.csdn.net/qq_/article/details/
http://blog.csdn.net/qq_/article/details/
Java学习这一部分其实也算是今天的重点,这一部分用来回答很多群里的朋友所问过的问题,那就是你是如何学习Java的,能不能给点建议?今天我是打算来点干货,因此咱们就不说一些学习方法和技巧了,直接来谈每个阶段要学习的内容甚至是一些书籍。这一部分的内容,同样适用于一些希望转行到Java的同学。
在大家看之前,我要先声明两点。1、由于我本人是Java后端开发出身,因此所推荐的学习内容是Java Web和Java后端开发的路线,非Java Web和Java后端开发的同学请适当参考其学习思想即可,切勿照搬。2、下面对于【第一部分】的推荐内容,目的是让你尽快成为一个可以参加工作的Java开发者,更适用于处于待业状态,准备转行Java的同学。
如果你是在校学生,务必要在学好基础(比如计算机系统、算法、编译原理等等)的前提下,再考虑去进行下面的学习。
第一部分:对于尚未做过Java工作的同学,包括一些在校生以及刚准备转行Java的同学。
一、Java基础首先去找一个Java的基础教程学一下,这里可以推荐一个Java学习交流的QQ群(群

我要回帖

更多关于 netty 内存池 的文章

 

随机推荐