Wetts's blog

Stay Hungry, Stay Foolish.

0%

转自:http://os.51cto.com/art/201205/334954.htm

PS1——默认提示符

如下所示,可以通过修改Linux下的默认提示符,使其更加实用。在下面的例子中,默认的PS1的值是\s-\v\$,显示出了shell的名称的版本。我们通过修改,可以使其显示用户名、主机名和当前工作目录。

  • \d :代表日期,格式为weekday month date,例如:”Mon Aug 1”
  • \H :完整的主机名称。例如:我的机器名称为:fc4.linux,则这个名称就是fc4.linux
  • \h :仅取主机的第一个名字,如上例,则为fc4,.linux则被省略
  • \t :显示时间为24小时格式,如:HH:MM:SS
  • \T :显示时间为12小时格式
  • \A :显示时间为24小时格式:HH:MM
  • \u :当前用户的账号名称
  • \v :BASH的版本信息
  • \w :完整的工作目录名称。家目录会以 ~代替
  • \W :利用basename取得工作目录名称,所以只会列出最后一个目录
  • \# :下达的第几个命令
  • \$ :提示字符,如果是root时,提示符为:# ,普通用户则为:$
前景 背景 颜色
30 40 黑色
31 41 红色
32 42 绿色
33 43 黄色
34 44 蓝色
35 45 紫红色
36 46 青蓝色
37 47 白色

\[\e[37;40m\][\[\e[32;40m\]\u\[\e[37;40m\]@\h \[\e[36;40m\]\w\[\e[0m\]]\n$
[用户名@计算机名 当前路径]

PS2——再谈提示符

一个非常长的命令可以通过在末尾加\使其分行显示。多行命令的默认提示符是>。 我们可以通过修改PS2,将提示符修改为”continue->” 。

1
2
3
4
ramesh@dev-db ~> myisamchk --silent --force --fast --update-state \
> --key_buffer_size=512M --sort_buffer_size=512M \
> --read_buffer_size=4M --write_buffer_size=4M \
> /var/lib/mysql/bugs/*.MYI

[注: 这里使用 “>” 作为默认提示符]

1
2
3
4
5
ramesh@dev-db ~> export PS2="continue-> "
ramesh@dev-db ~> myisamchk --silent --force --fast --update-state \
continue-> --key_buffer_size=512M --sort_buffer_size=512M \
continue-> --read_buffer_size=4M --write_buffer_size=4M \
continue-> /var/lib/mysql/bugs/*.MYI

[注: 与上面类似,用 “continue-> “ 作提示符]

当用\使长命令分行显示,我发现非常易读。当然我也见过有的人不喜欢分行显示命令

PS3——Shell脚本中使用select时的提示符

你可以像下面示范的那样,用环境变量PS3定制shell脚本的select提示:

不使用PS3的脚本输出:

1
2
3
4
5
6
7
8
9
10
ramesh@dev-db ~> cat ps3.sh
select i in mon tue wed exit
do
case $i in
mon) echo "Monday";;
tue) echo "Tuesday";;
wed) echo "Wednesday";;
exit) exit;;
esac
done
1
2
3
4
5
6
7
8
ramesh@dev-db ~> ./ps3.sh
1) mon
2) tue
3) wed
4) exit
#? 1
Monday
#? 4

[注: 缺省的提示符是 #?]

使用PS3的脚本输出:

1
2
3
4
5
6
7
8
9
10
11
ramesh@dev-db ~> cat ps3.sh
PS3="Select a day (1-4): "
select i in mon tue wed exit
do
case $i in
mon) echo "Monday";;
tue) echo "Tuesday";;
wed) echo "Wednesday";;
exit) exit;;
esac
done
1
2
3
4
5
6
7
8
ramesh@dev-db ~> ./ps3.sh
1) mon
2) tue
3) wed
4) exit
Select a day (1-4): 1
Monday
Select a day (1-4): 4

[注: 设置了PS3变量后,命令提示符已经成为 “Select a day (1-4):”]

PS4——PS4-“set -x”用来修改跟踪输出的前缀

如果你像下面那样在调试模式下的脚本中,PS4环境变量可以定制提示信息:

没有设置PS4时的shell脚本输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ramesh@dev-db ~> cat ps4.sh

set –x
echo "PS4 demo script"
ls -l /etc/ | wc –l du -sh ~

ramesh@dev-db ~> ./ps4.sh
++ echo 'PS4 demo script'
PS4 demo script
++ ls -l /etc/
++ wc –l
243
++ du -sh /home/ramesh
48K /home/ramesh

[注: 当使用sex -x跟踪输出时的提示符为 ++]
设置PS4后的脚本输出:

PS4在ps.sh中定义了下面两个变量

  • $0 显示当前的脚本名
  • $LINENO 显示的当前的行号
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    ramesh@dev-db ~> cat ps4.sh
    export PS4='$0.$LINENO+ '
    set -x
    echo "PS4 demo script"
    ls -l /etc/ | wc -l
    du -sh ~

    ramesh@dev-db ~> ./ps4.sh
    ../ps4.sh.3+ echo 'PS4 demo script'
    PS4 demo script
    ../ps4.sh.4+ ls -l /etc/
    ../ps4.sh.4+ wc -l
    243
    ../ps4.sh.5+ du -sh /home/ramesh
    48K /home/ramesh
    [注: 使用PS4后使 “{script-name}.{line-number}+” 成为set –x的命令提示符]

Eclipse创建Android项目时,会多出一个appcompat_v7的问题


问题描述:

使用eclipse创建一个Android项目时,发现project列表中会多创建出一个appcompat_v7项目,再创建一个Android项目时,又会再多出一个appcompat_v7_2,如果再次创建,会以此类推地创建出appcompat_v7_x格式的“多余项目”出来(此情况在ADT升级为22.6.x版本后出现,22.3.x前的版本不会有)

阅读全文 »

android SDK 文档目录结构

  1. add-ons 这里面保存着附加库,比如google Maps,当然你如果安装了OPhone SDK,这里也会有一些类库在里面。

  2. docs 这里面是Android SDK API参考文档,所有的API都可以在这里查到。

阅读全文 »

关闭开启

1
2
3
4
5
6
7
8
1) 重启后生效
开启: chkconfig iptables on
关闭: chkconfig iptables off

2) 即时生效,重启后失效
开启: service iptables start
关闭: service iptables stop
重启: service iptables restart
阅读全文 »

转自:http://yuninglovekefan.blog.sohu.com/263559230.html

INSERT INTO ON DUPLICATE KEY UPDATE 与 REPLACE INTO,两个命令可以处理重复键值问题,在实际上它之间有什么区别呢?

前提条件是这个表必须有一个唯一索引或主键。

  1. REPLACE 发现重复的先删除再插入,如果记录有多个字段,在插入的时候如果有的字段没有赋值,那么新插入的记录这些字段为空。
  2. INSERT 发现重复的是更新操作。在原有记录基础上,更新指定字段内容,其它字段内容保留。

这样 REPLACE 的操作成本要大于 INSERT ON DUPLICATE KEY UPDATE,按道理应该选用 INSERT ON DUPLICATE KEY UPDATE

INSERT语法

1
2
3
4
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name [(col_name,...)]
VALUES ({expr | DEFAULT},...),(...),...
[ ON DUPLICATE KEY UPDATE col_name=expr, ... ]

或:

1
2
3
4
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
SET col_name={expr | DEFAULT}, ...
[ ON DUPLICATE KEY UPDATE col_name=expr, ... ]

或:

1
2
3
4
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name [(col_name,...)]
SELECT ...
[ ON DUPLICATE KEY UPDATE col_name=expr, ... ]

一、DELAYED 的使用

使用延迟插入操作

DELAYED 调节符应用于 INSERT 和 REPLACE 语句。当 DELAYED 插入操作到达的时候,服务器把数据行放入一个队列中,并立即给客户端返回一个状态信息,这样客户端就可以在数据表被真正地插入记录之前继续进行操作了。如果读取者从该数据表中读取数据,队列中的数据就会被保持着,直到没有读取者为止。接着服务器开始插入延迟数据行(delayed-row)队列中的数据行。在插入操作的同时,服务器还要检查是否有新的读取请求到达和等待。如果有,延迟数据行队列就被挂起,允许读取者继续操作。当没有读取者的时候,服务器再次开始插入延迟的数据行。这个过程一直进行,直到队列空了为止。

几点要注意事项:

  • INSERT DELAYED 应该仅用于指定值清单的 INSERT 语句。服务器忽略用于 INSERT DELAYED…SELECT 语句的 DELAYED。
  • 服务器忽略用于 INSERT DELAYED…ON DUPLICATE UPDATE 语句的 DELAYED。
  • 因为在行被插入前,语句立刻返回,所以您不能使用 LAST_INSERT_ID() 来获取 AUTO_INCREMENT 值。AUTO_INCREMENT 值可能由语句生成。
  • 对于 SELECT 语句,DELAYED 行不可见,直到这些行确实被插入了为止。
  • DELAYED 在从属复制服务器中被忽略了,因为 DELAYED 不会在从属服务器中产生与主服务器不一样的数据。

注意,目前在队列中的各行只保存在存储器中,直到它们被插入到表中为止。这意味着,如果您强行中止了 mysqld(例如,使用 kill -9

或者如果 mysqld 意外停止,则所有没有被写入磁盘的行都会丢失。

二、IGNORE 的使用

IGNORE 是 MySQL 相对于标准 SQL 的扩展。如果在新表中有重复关键字,或者当 STRICT 模式启动后出现警告,则使用 IGNORE 控制 ALTER TABLE 的运行。如果没有指定 IGNORE,当重复关键字错误发生时,复制操作被放弃,返回前一步骤。如果指定了 IGNORE,则对于有重复关键字的行,只使用第一行,其它有冲突的行被删除。并且,对错误值进行修正,使之尽量接近正确值。insert ignore into tb(...) value(...) 这样不用校验是否存在了,有则忽略,无则添加

三、ON DUPLICATE KEY UPDATE 的使用

如果您指定了 ON DUPLICATE KEY UPDATE,并且插入行后会导致在一个 UNIQUE 索引或 PRIMARY KEY 中出现重复值,则执行旧行 UPDATE。例如,如果列 a 被定义为 UNIQUE,并且包含值 1,则以下两个语句具有相同的效果:

1
mysql> INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1;
1
mysql> UPDATE table SET c=c+1 WHERE a=1;

如果行作为新记录被插入,则受影响行的值为1;如果原有的记录被更新,则受影响行的值为2。

注释:如果列b也是唯一列,则INSERT与此UPDATE语句相当:

1
mysql> UPDATE table SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;

如果 a=1 OR b=2 与多个行向匹配,则只有一个行被更新。通常,您应该尽量避免对带有多个唯一关键字的表使用 ON DUPLICATE KEY 子句。

您可以在UPDATE子句中使用 VALUES(col_name)函数从 INSERT…UPDATE 语句的 INSERT 部分引用列值。换句话说,如果没有发生重复关键字冲突,则 UPDATE子 句中的 VALUES(col_name) 可以引用被插入的 col_name 的值。本函数特别适用于多行插入。VALUES() 函数只在 INSERT…UPDATE 语句中有意义,其它时候会返回 NULL。

示例:

1
mysql> INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6) ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);

本语句与以下两个语句作用相同:

1
2
3
mysql> INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=3;

mysql> INSERT INTO table (a,b,c) VALUES (4,5,6) ON DUPLICATE KEY UPDATE c=9;

当您使用 ON DUPLICATE KEY UPDATE 时,DELAYED 选项被忽略。


总结:

  • DELAYED 做为快速插入,并不是很关心失效性,提高插入性能。
  • ignore 只关注主键对应记录是不存在,无则添加,有则忽略。
  • ON DUPLICATE KEY UPDATE 在添加时操作,关注非主键列,注意与 ignore 的区别。有则更新指定列,无则添加。

Java 中的引用


Java 官方 API 中是这么对可达性来分类的:

从最强到最弱,不同的可到达性级别反映了对象的生命周期。在操作上,可将它们定义如下:

  • 如果某一线程可以不必遍历所有引用对象而直接到达一个对象,则该对象是强可到达对象。新创建的对象对于创建它的线程而言是强可到达对象。
  • 如果一个对象不是强可到达对象,但通过遍历某一软引用可以到达它,则该对象是 软可到达 对象。
  • 如果一个对象既不是强可到达对象,也不是软可到达对象,但通过遍历弱引用可以到达它,则该对象是弱可到达对象。当清除对某一弱可到达对象的弱引用时,便可以终止此对象了。
  • 如果一个对象既不是强可到达对象,也不是软可到达对象或弱可到达对象,它已经终止,并且某个虚引用在引用它,则该对象是虚可到达对象。
  • 最后,当不能以上述任何方法到达某一对象时,该对象是不可到达 对象,因此可以回收此对象。

-

  • 强引用
    如果一个对象具有强引用,那就类似于必不可少的生活用品,垃圾回收器绝不会回收它。当内存空间不足,Java 虚拟机宁愿抛出 OutOfMemoryError 错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题。

  • 软引用(SoftReference)
    如果一个对象只具有软引用,那就类似于可有可物的生活用品。如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。

软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。

  • 弱引用(WeakReference)
    如果一个对象只具有弱引用,那就类似于可有可物的生活用品。弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。

弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java 虚拟机就会把这个弱引用加入到与之关联的引用队列中。

  • 虚引用(PhantomReference)
    “虚引用”顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。

虚引用主要用来跟踪对象被垃圾回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。程序如果发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

-

利用软引用和弱引用来避免 OOM

  • 假如有一个应用需要读取大量的本地图片,如果每次读取图片都从硬盘读取,则会严重影响性能,但是如果全部加载到内存当中,又有可能造成内存溢出,此时使用软引用可以解决这个问题。
  • 设计思路是:用一个HashMap来保存图片的路径和相应图片对象关联的软引用之间的映射关系,在内存不足时,JVM会自动回收这些缓存图片对象所占用的空间,从而有效地避免了OOM的问题。在Android开发中对于大量图片下载会经常用到。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private Map<String, SoftReference<Bitmap>> imageCache = new HashMap<String, SoftReference<Bitmap>>();
public void addBitmapToCache(String path) {
// 强引用的Bitmap对象
Bitmap bitmap = BitmapFactory.decodeFile(path);
// 软引用的Bitmap对象
SoftReference<Bitmap> softBitmap = new SoftReference<Bitmap>(bitmap);
// 添加该对象到Map中使其缓存
imageCache.put(path, softBitmap);
}
public Bitmap getBitmapByPath(String path) {
// 从缓存中取软引用的Bitmap对象
SoftReference<Bitmap> softBitmap = imageCache.get(path);
// 判断是否存在软引用
if (softBitmap == null) {
return null;
}
// 取出Bitmap对象,如果由于内存不足Bitmap被回收,将取得空
Bitmap bitmap = softBitmap.get();
return bitmap;
}

-

WeakHashMap

  • 在Java集合中有一种特殊的Map类型:WeakHashMap, 在这种 Map 中存放了键对象的弱引用,当一个键对象被垃圾回收,那么相应的值对象的引用会从 Map 中删除。WeakHashMap 能够节约存储空间,可用来缓存那些非必须存在的数据。
WeakHashMap 案例
  • 无意识对象保留最常见的原因是使用 Map 将元数据与临时对象(transient object)相关联。假定一个对象具有中等生命周期,比分配它的那个方法调用的生命周期长,但是比应用程序的生命周期短,如客户机的套接字连接。需要将一些元数据与这个套接字关联,如生成连接的用户的标识。在创建Socket时是不知道这些信息的,并且不能将数据添加到 Socket 对象上,因为不能控制 Socket 类或者它的子类。
  • 这种方法的问题是元数据的生命周期需要与套接字的生命周期挂钩,但是除非准确地知道什么时候程序不再需要这个套接字,并记住从 Map 中删除相应的映射,否则,Socket 和 User 对象将会永远留在 Map 中,远远超过响应了请求和关闭套接字的时间。这会阻止 Socket 和 User 对象被垃圾收集,即使应用程序不会再使用它们。这些对象留下来不受控制,很容易造成程序在长时间运行后内存爆满。除了最简单的情况,在几乎所有情况下找出什么时候 Socket 不再被程序使用是一件很烦人和容易出错的任务,需要人工对内存进行管理。
  • 在Java集合中有一种特殊的Map类型 WeakHashMap,在这种Map中存放了键对象的弱引用,当一个键对象被垃圾回收器回收时,那么相应的值对象的引用会从 Map 中删除。WeakHashMap 能够节约存储空间,可用来缓存那些非必须存在的数据。关于 Map 接口的一般用法。

慢查询日志

配置

方法一:

  1. 找到 mysql的 配置文件 my.cnf
  2. 在[mysqld]下方加入慢查询的配置语句
    1
    2
    3
    4
    5
    6
    # log-slow-queries: 代表MYSQL慢查询的日志存储目录, 此目录文件一定要有写权限
    log-slow-queries = /usr/local/mysql/mysql-slow.log
    # long_query_time: 最长执行时间
    long_query_time = 2
    # log下来没有使用索引的query
    log-queries-not-using-indexes
  3. 重启 MySQL(service mysqld restart)

方法二:

  1. 执行 set global log_slow_queries = on;

    慢日志默认放在MySQL目录下,记录执行时间超过 2s 的 sql

日志分析

慢日志分析命令为 mysqldumpslow

  • 参数:
    1
    2
    3
    4
    5
    6
    7
    8
    -s ORDER what to sort by (t, at, l, al, r, ar etc), ‘at’ is default  
    是order的顺序,说明写的不够详细,俺用下来,包括看了代码,主要有c,t,l,r和ac,at,al,ar,分别是按照query次数,时间,lock的时间和返回的记录数来排序,前面加了a的时倒叙。

    -t NUM just show the top n queries
    是top n的意思,即为返回前面多少条的数据。

    -g PATTERN grep: only consider stmts that include this string
    后边可以写一个正则匹配模式,大小写不敏感的。
  • 例子:
    1
    2
    3
    4
    5
    6
    7
    8
    # 访问次数最多的20个sql语句
    mysqldumpslow -s c -t 20 host-slow.log

    # 记录集最多的20个sql
    mysqldumpslow -s r -t 20 host-slow.log

    # 前10条里面含有左连接的sql语句
    mysqldumpslow -t 10 -s t -g “left join” host-slow.log

  • 修改tinyint长度
    tinyint 长度为1,指的是占用1个字节空间,TINYINT(1)、BOOL、BOOLEAN 所占用的存储空间和 TINYINT 一样,都是一个字节;
    TINYINT(1) 只是在显示的时候作为一个位进行输出而已,所以设置成TINYINT(4)就可以了

阅读全文 »

转自:http://www.iteye.com/topic/1116193

常量

在JDK1.5 之前,我们定义常量都是:public static fianl....。现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法。

1
2
3
public enum Color {
RED, GREEN, BLANK, YELLOW
}

switch

JDK1.6之前的switch语句只支持int,char,enum类型,使用枚举,能让我们的代码可读性更强。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
enum Signal {  
GREEN, YELLOW, RED
}
public class TrafficLight {
Signal color = Signal.RED;
public void change() {
switch (color) {
case RED:
color = Signal.GREEN;
break;
case YELLOW:
color = Signal.RED;
break;
case GREEN:
color = Signal.YELLOW;
break;
}
}
}

向枚举中添加新方法

如果打算自定义自己的方法,那么必须在enum实例序列的最后添加一个分号。而且 Java 要求必须先定义 enum 实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public enum Color {  
RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
// 成员变量
private String name;
private int index;
// 构造方法
private Color(String name, int index) {
this.name = name;
this.index = index;
}
// 普通方法
public static String getName(int index) {
for (Color c : Color.values()) {
if (c.getIndex() == index) {
return c.name;
}
}
return null;
}
// get set 方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
}

覆盖枚举的方法

下面给出一个toString()方法覆盖的例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public enum Color {  
RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
// 成员变量
private String name;
private int index;
// 构造方法
private Color(String name, int index) {
this.name = name;
this.index = index;
}
//覆盖方法
@Override
public String toString() {
return this.index+"_"+this.name;
}
}

实现接口

所有的枚举都继承自java.lang.Enum类。由于Java 不支持多继承,所以枚举对象不能再继承其他类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public interface Behaviour {  
void print();
String getInfo();
}
public enum Color implements Behaviour{
RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
// 成员变量
private String name;
private int index;
// 构造方法
private Color(String name, int index) {
this.name = name;
this.index = index;
}
//接口方法
@Override
public String getInfo() {
return this.name;
}
//接口方法
@Override
public void print() {
System.out.println(this.index+":"+this.name);
}
}

使用接口组织枚举

1
2
3
4
5
6
7
8
public interface Food {  
enum Coffee implements Food{
BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO
}
enum Dessert implements Food{
FRUIT, CAKE, GELATO
}
}

关于枚举集合的使用

java.util.EnumSet和java.util.EnumMap是两个枚举集合。EnumSet保证集合中的元素不重复;EnumMap中的 key是enum类型,而value则可以是任意类型。关于这个两个集合的使用就不在这里赘述,可以参考JDK文档。