java并发编程2-创建和运行线程

使用Tread创建线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.wsx.test;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ThreadTest {
@Test
public void test1() {
final Logger logger = LoggerFactory.getLogger(ThreadTest.class);
Thread thread = new Thread() {
@Override
public void run() {
logger.debug("running");
}
};
thread.setName("t1");
thread.start();
logger.debug("running");
}
}

Read More

spring11-Jdbctemplate

JdbcTemplate

测试写法

1
2
3
4
5
6
7
8
9
10
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate",JdbcTemplate.class);
// 保存
jt.update("insert into account(name,money)values(?,?)","eee",3333f);
// 更新
jt.update("update account set name=?,money=? where id=?","test",4567,7);
// 删除
jt.update("delete from account where id=?",8);
// 查询
List<Account> account = jt.query("select * from account where money>?",new BeanPropertyRowMapper<Account>(Account.class),1000f);

DAO中的JdbcTemplate

上面的代码实际上只能用于简单的测试,我们正确的做法应该还是使用DAO实现,注意到使用DAO实现的时候肯定要在类中创建jdbcTemplate,如果我们有多个DAO就会导致份重复的代码,这时可以让他们继承一个JdbcDaoSupport来实现,而这个类spring又恰好为我们提供了。但是只能通过xml注入,你想要用注解注入的话就只能自己写一个。

mysql游标

游标允许我们遍历结果集

不想多说,我只是感觉好复杂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
create table test(id int);
delimiter // #定义标识符为双斜杠
drop procedure if exists test; #如果存在test存储过程则删除
create procedure test() #创建无参存储过程,名称为test
begin
declare i int; #申明变量
declare id_ int;
declare done int;
declare cur cursor for select id from test;
declare continue handler for not found set done = 1;
open cur;
read_loop: loop
fetch cur into id_;
if done = 1 then
leave read_loop;
end if;
select id_;
end loop;
close cur;
end
// #结束定义语句
call test(); #调用存储过程

网易笔试

第一题

输入一个n,表示n个点的完全图,输入m表示后续有m个操作,输入s表示你站在s点这个位置
接下来m行,每行两个数字x,y
如果x=0 表示与y相连的所有边断开
否则 表示边x-y断开
你需要输出一个数x,表示这m个操作的前x个操作可以让s点与其他所有点断开连接

1
2
3
4
5
6
7
8
9
10
11
12
13
set<int>se;
for(int i=1;i<=m;i++){
cin>>x>>y;
if(x==0) {
if(y==s) return i;
else se.insert(y);
}else {
if(x==s) se.inesrt(y);
if(y==s) se.insert(x);
}
if(se.size()==n) return i;
}
return 0;

怎么说呢,我就是这样写的,显然se.size()==n写错了,应该说n-1,跟yg讲这题的时候才想起来,我原地爆炸了,一直怀疑题目有问题,然后只过了10%,到最后都没找到bug

Read More

linux指令学习

MAN 操作手册

学linux,必须知道如何使用man,首先是安装man,或者在这里逛逛

1
yum -y install man-pages

SCP

上传本地文件到服务器

1
scp -P [ssh端口] /path/filename username@serverhost:/path   

下载HTTP文件

下载东西可以使用curl指令,如

1
curl baidu.com -O -L

也可以使用wget指令,如

1
wget baidu.com

Linux运行级别

linux一共有7个级别,分别为
0关机、
1单用户、
2无网多用户、
3有网多用户,
4保留,
5图形界面,
6重启。
在文件/etc/inittab中指定了级别。

查看运行级别

查看文件/etc/inittab

修改运行级别

1
init 3

如何找回root密码

进入单用户模式,然后修改密码,因为进入单用户模式不需要密码就可以登陆。
进入grub中,按e编辑指令,修改kernel,输入1进入单用户级别,输入b启动,用passwd root修改密码

mkdir

在用户文件夹下创建hello

1
mkdir ~/hello 

多级目录需要加上-p参数

1
mkdir ~/h/h/h

rmdir

删除空文件夹

1
rmdir ~/hello

删除非空文件夹

1
rm -rf

touch

创建文件,我常用vim

1
touch a.txt b.txt c.txt 

cp

将a.txt拷贝到用户目录下

1
cp a.txt ~/

将a这个文件夹全部拷贝到用户目录,-r指的是递归

1
cp -r a/ ~/

\cp可以强制覆盖不提示,在mac中直接覆盖了,不需要\cp

rm

删除a.txt,

1
rm a.txt

删除目录a, -r为递归

1
rm -r a/

删除目录a,-f为不提示 可与-r合并为-rf

1
rm -r -f a/

mv

将a.txt重命名为b.txt

1
mv a.txt b.txt

将a.txt一定到用户目录,如果那有的话,mac不提示是否替换,直接替换,有点不人道了。

1
mv a.txt ~/

cat

cat是浏览文件
就能看到配置文件了

1
cat ~/.vimrc

-n 能够显示行号

1
cat -n ~/.vimrc

more是一个类似于vim的东西,能够把文件分页,用空格看下一行,用enter看下一页,用<C-F>和<C-B>翻页,用=输出行号,用fb也可以翻页。

1
cat -n ~/.vimrc | more

more

直接完成

1
more ~/.vimrc 

less

基于显示的懒加载方案,打开文件非常快
几乎和more一样,就是开大文件快一点,可以用来打开日志。

1
less ~/.vimrc

> 和>>

>是输出重定向,会覆盖内容,>>是追加,不会覆盖

例子

ls -l 会输出一些内容,这些叫输出,>a.txt会写入a.txt,当然也可以用>>来追加,后面只演示>,不演示>>了

1
ls -l > a.txt

例子2

将cat的输出重定向到b.txt中

1
cat a.txt > b.txt

echo

输出 abcde

1
echo "abcde"

将abcde写入a.txt

1
echo "abcde" > a.txt

cal

cal显示日历
将日历输出到a.txt

1
cal > a.txt 

echo

一般用于输出信息,
输出了abc

1
echo "abc"

输出环境变量,

1
echo $PATH

head

查看文件的前几行
看vim配置文件前10行

1
head ~/.vimrc

看vim配置文件的前20行,-n表示行数

1
head -n 20 ~/.vimrc

tail

查看结尾几行,同上
监控a.txt,当他被追加的时候,输出追加的信息

1
tail -f a.txt

ln

建立软链接(快捷方式)
创建一个用户目录的软链接到当前目录,这个软链接叫mylink

1
ln -s ~ mylink

history

查看最近执行的指令
mac中不太一样,history 10 表示查看第10条指令到现在的指令
查看最近执行的10条指令

1
history 10

执行第10调指令

1
!10

date

date可以看到时间,后面是格式设置

1
date "+%Y-%m-%d 星期%w %H:%M:%S"

设置日期

-s 表示设置时间

1
date -s "2021-1-1 1:1:1"

cal

cal直接查看当前月的日历
看2020n年的日历

1
cal 2020 

find

在用户文件夹下找名为.vimrc的文件

1
find ~ -name .vimrc

在用户文件夹下找名为.vimrc属于用户s的文件

1
find ~ -user s -name .vimrc

在用户文件夹下找大于100M的文件

1
find ~ -size +100M

在用户文件夹下找小于100M的文件

1
find ~ -size -100M

在用户文件夹下找等于100M的文件

1
find ~ -size 100M

通配符

1
find ~ -name *.txt

locate

根据数据库快速定位文件的位置,
更新数据库

1
updatedb

根据数据库快速定位a.txt

1
locate a.txt 

管道

将前一个指令的输出传递给后一个指令处理

1
|

grep

寻找let,并输出行号和行数据,-n表示输出行号,-i表示不区分大小写,

1
grep -n -i let ~/.vimrc

通过管道将cat的结果传递给grep,同上

1
cat ~/.vimrc | grep -ni let

gzip gunzip

将hello.txt压缩为hello.txt.gz

1
gzip hello.txt 

将hello.txt.gz解压为hello.txt

1
gunzip hello.txt.gz

zip 与 unzip

把用户目录下的所有文件压缩到res.zip中

1
zip -r res.zip ~

把res.zip解压到~/res中

1
unzip -d ~/res res.zip

rar 与 unrar

有这东西,很少用

tar

-z是打包同时压缩,-c是产生.tar文件,-v是显示详细信息,-f是指定压缩后的文件名 res.tar.gz是打包后的文件,其后为打包文件

1
-zcvf res.tar.gz a.txt b.txt

对a文件夹打包

1
-zcvf res.tar.gz a/

解压到当前目录

1
-zxvf res.tar.gz 

指定解压到~中

1
-zxvf res.tar.gz -c ~ 

netstat

netstat可以显示网络状态,

script
1
netstat -a

netstat可以显示网卡

script
1
netstat -i

Read More

redis

nosql

随时大规模高并发的出现,传统关系型数据库已经碰到了很大的问题,他难以提供更快的数据访问速度了,这导致数据库成为了瓶颈。人们提出not only sql的一种理念,就是我们不能仅仅依靠关系型数据库。

非关系型数据库

指的是没有关系的数据库,即不是二纬表,而是KV对。

redis

redis 就是其中的一个非关系型数据库,他是单线程,将数据储存在内存中的数据库,他支持丰富的数据类型,包括string,list,set,hash,zset

redis持久化

第一种是rdb方案,他将内存的数据定期储存到磁盘中,由于数据的空间问题,一般15分钟一次,第二种是aof方案,他将读取的数据定期增加到磁盘中,由于我们只是添加,一般1s一次。rdb本质为整体储存,aof为懒惰式储存,他储存的是操作,而不是数据库。

redis事务

redis半支持事务,语法错误回滚,但运行错误不会。

redis主从复制

主机写,从机读,

redis哨兵模式

当主机挂了以后,通过投票在从机中选出新的主机

缓存雪崩

大量的缓存同时失效,导致原本应该访问缓存的请求由于找不到数据,都去查询数据库,造成数据库CPU和内存巨大的压力
解决方案:对数据库加锁,或者让缓存失效时间分散开

缓存穿透

查询数据库中没有的数据,导致每次都要进入数据库查询
解决方案: 布隆过滤器,或者把数据库中不存在的数据也存入缓存设为空

布隆过滤器

引入多个相互独立的哈希函数,对数据库中的数据进行哈希,然后存入位图中,这里的多个确保了精度

缓存击穿

由于缓存中某条热点数据过期,导致大量高并发的请求击穿缓存进入数据库,导致数据库巨大的压力
解决方案: 热点数据永不过期或者访问数据库前加互斥锁, 这里为什么不是依靠数据库自己的锁呢,我认为能早处理的话就早处理,不要给数据库加压。

缓存预热

系统上线以后,将某些相关的缓存数据之间加入到缓存系统中

缓存更新

根据具体业务需求去自定义缓存淘汰机制,定期清理或者当请求来临的时候更新

缓存降级

当访问量增大,非核心服务影响核心服务的性能时,自动或者人工地让缓存尽量少查询数据库,尽管这可能导致少量的错误,但是我们的目标时系统的高可用性。

memcache、mongoDB、redis

性能都高,但是redis和memcache比mongodb强一点点
memcache只能是字符串,mongodb更加类似与关系型数据库,redis支持丰富的数据类型
redis用主从一致、哨兵机制保护数据,memcache没有冗余数据,mongoDB有主从一致、内部选举、auto sharding保护数据
redis支持rdb和aof,memcache没有持久化,mongodb用binlog
Memcache用cas保存一致性,redis事务性较差,mongodb没有事务

参考资料

redis面试题
缓存穿透、缓存击穿、缓存雪崩区别和解决方案
Redis与Memcached的区别