git 和 svn 的区别
1.git 是分布式的,svn不是,每个开发人员从中心版本库/服务器上chect out代码后会在自己的机器上克隆一个自己的版本库。
2.git 把内容安装元数据进行存储,svn是按照文件进行存储
常见的sql问题考察
- 查询学生每一个科目的最高分
select class,max(score) from table group by class;
- 查询每个科目都大于80分的学生姓名
只要有一个小于80就加入集合
select distinct name from table where name not in (select name from table score <= 80);
- 查询每一个学生的最高的科目
select a.student,a.class from table a ,(select student ,max(score) as max_score from table group by student) b where a.score = b.max_score and a.student = b.student;
- 查询平均分大于80分的学生
select student from table group by student having avg(score) > 80;
- 查询有两个分数相同的学生
select student,score,count(1) group by student,score having count(score) > 2;
随机打乱数组
可以保证扫面点左边的数字都是尚未确定位置的,而右边的数字都是已经安排好位置的
public static <T> void swap(T[] a, int i, int j){
T temp = a[i];
a[i] = a[j];
a[j] = temp;
}
public static <T> void shuffle(T[] arr) {
int length = arr.length;
for ( int i = length; i > 0; i-- ){
int randInd = rand.nextInt(i);
swap(arr, randInd, i - 1);
}
}
32位的计算机最多可以管理4G的内存
2 ^ 32 = 4G
2 ^ 64 = G 当然这是理论值
冯诺依曼内存模型
什么是守护进程?
-
守护进程(daemon)是生存期长的一种进程,没有控制终端,的后台运行的进程。
-
需要注意的是,用户层守护进程的父进程是 init进程(进程ID为1)
-
守护进程程序的名称通常以字母“d”结尾
什么是临界区?如何解决进程间的冲突
- 多个进程进入临界区一次只能进入一个
- 如果一个已经进入,其他都只能等待
- 进入临界区,必须在有限时间内退出,以便其他进程进入临界区
- 自己时间不能进去临界区,应该让出避免“忙等”
一个方法加了Synchronized ,其他线程能否进入此对象的其他方法;
1.如果其他方法没加synchronized 可以进去;
2.如果这个方法内部调用wait,其他synchronized方法也可以进去,没有调wait,不能进去其他synchronized方法;
3.如果其他方法是静态的他用的同步锁和当前不同可以进去;
如何保证线程的安全性
保证可见性和原子性
java 初始化顺序
- 父类静态变量静态块
- 子类的静态变量静态块
- 父类变量初始化块构造方法
- 子类变量初始化块构造方法
mysql 为什么默认隔离级别是可重复读?
这是因为,mysql 如果打开语句级binlog就不支持,读已提交和读未提交两个事物隔离级别;
mysql 设置默认隔离级别为可重复读的原因是:
- 读已提交,会有不可重复读的问题
- binlog 要求sql串行化;
其次,mysql的可重复读,在一定程度上也避免了幻读的问题;
InnoDB通过gap锁来避免幻象,从而实现SQL的可串行化,保证Binlog的一致性。
其实,RR隔离级别的防止幻象主要是针对写操作的,即只保证写操作的可串行化,因为只有写操作影响Binlog;而读操作是通过MVCC来保证一致性读。
mysql 查询慢的原因以及优化步骤
- 设置关闭缓存set_no_cache,看看是否真的慢;
- 每个字段单独查询,查看他们的区分度和查询的速度
- 通过explain查看执行计划是否一致
- order by limit 形式的sql语句让排序的表优先查
- 加索引时参照建索引的几大原则
原则有:
- 最左前缀匹配原则
- 尽量选择区分度高的列作为索引,区分度的公式是count(distinct col)/count(*)
- 尽量的扩展索引,不要新建索引。
隔离级别RR下的死锁情况
TX1 TX2
begin;
update b set name2='test' where id=2999; 对id:2999加LOCK_X锁
update b set name2='test' where id=999;
使用insert select 查询 select 会加锁
begin;
insert into a select * from b where id in (996,997,998,999,2995,2996,2997,2998,2999);对id:在加锁到996,997,998,999,2995,2996加LOCK_S锁,在对id:2997加锁前睡眠30秒,为下面的update语句腾出时间)
update b set name2='test' where id=999;对id:999加LOCK_X锁等待但发现已经加LOCK_S锁,需等待
描述:一个事务内要更新两个id的数据,id = 2999,id = 999; 另一个个事务在他执行了一个更新语句后,要执行包含id = 2999.id = 999 的插入,但是需要等待第一个事务释放锁,但是第一个事务的第二个语句,又需要第二个事务释放id = 999 的锁,最终形成死锁;
尽量少使用insert search
如何删除表的重复数据;
思路查找出最小的id,只保留最小的其他删除
delete from order where id not in (select id from ( select min(id) as id from order group by order_number) as b);
delete from table where id not in (select min(id) from table group by name having count(name)>1) and id in (select id group by name having count(name)>1)
使用 mysql 做队列
开启两个事务来读取状态,会将所有未消费的进行锁住;
update user set session=CONNECTION_ID(),status='using' where status='un_use' limit 2;
为什么重写 equals 要重新 hashcode;
保证hash时,相同的hash到同一个位置
String 和 StringBuilder 的区别
String 和 StringBuilder 是效率和内存分配结果
当我们通过+来拼接字符串时,编译器会自动替我们优化成StringBuilder来拼接
- 目前 String 和 StringBuilder 编译优化后一样
- String 在循环中操作会导致很多StringBuilder,反编译以后的代码,我们可以发现,原来字符串常量在拼接过程中,是将String转成了StringBuilder后,使用其append方法进行处理的。
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=3, args_size=1
0: ldc #2 // String
2: astore_1
3: iconst_0
4: istore_2
5: iload_2
6: bipush 10
8: if_icmpge 36
11: new #3 // class java/lang/StringBuilder
14: dup
15: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
18: aload_1
19: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
22: iload_2
23: invokevirtual #6 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
26: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
29: astore_1
30: iinc 2, 1
33: goto 5
36: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
39: aload_1
40: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
43: return
LineNumberTable:
line 10: 0
line 11: 3
line 12: 11
line 11: 30
line 14: 36
line 15: 43
LocalVariableTable:
Start Length Slot Name Signature
5 31 2 i I
0 44 0 args [Ljava/lang/String;
3 41 1 res Ljava/lang/String;
StackMapTable: number_of_entries = 2
frame_type = 253 /* append */
offset_delta = 5
locals = [ class java/lang/String, int ]
frame_type = 250 /* chop */
offset_delta = 30
}
java 泛型实现的原理?
概念用法:
Java中的泛型基本上都是在编译器这个层次来实现的。在生成的Java字节码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会在编译器在编译的时候去掉。这个过程就称为类型擦除。
List<object>和List<String>
泛型擦除:
public void test(List<Integer> li)
public void test(List<String> Li)
编译出错
在程序中定义了一个ArrayList泛型类型实例化为Integer的对象,如果直接调用add方法,那么只能存储整形的数据。不过当我们利用反射调用add方法的时候,却可以存储字符串。这说明了Integer泛型实例在编译之后被擦除了,只保留了原始类型。
类型擦除引起的问题及解决方法?
- 先检查再编译,既然类型擦除了,如何保证我们只能使用泛型变量限定的类型呢?java是如何解决这个问题的呢?java编译器是通过先检查代码中泛型的类型,然后再进行类型擦除,在进行编译的。
- 在Java中,像下面形式的引用传递是不允许的:
ArrayList<String> arrayList1=new ArrayList<Object>();//编译错误
ArrayList<Object> arrayList1=new ArrayList<String>();//编译错误
3、类型擦除与多态的冲突和解决方法,我们本意重写setValue和getValue方法的子类,竟然有4个方法,其实不用惊奇,最后的两个方法,就是编译器自己生成的桥方法。可以看到桥方法的参数类型都是Object,也就是说,子类中真正覆盖父类两个方法的就是这两个我们看不到的桥方法。而打在我们自己定义的setvalue和getValue方法上面的@Oveerride只不过是假象。而桥方法的内部实现,就只是去调用我们自己重写的那两个方法。
所以,虚拟机巧妙的使用了巧方法,来解决了类型擦除和多态的冲突。
如何拷贝一个数组
System.arrayCopy()
线程池如何做到重用?
使用预分配先创建一定数量的核心,执行完会继续阻塞,等待新的任务,其他大于核心线程数的线程会在一定时间后进行回收;
jvm能否自己关闭线程池
如果程序中不再持有线程池的引用,并且线程池中没有线程时,线程池将会自动关闭。
线程池自动关闭的两个条件:1、线程池的引用不可达;2、线程池中没有线程;
这里对于条件2解释一下,线程池中没有线程是指线程池中的所有线程都已运行完自动消亡。
- 然而我们常用的FixedThreadPool的核心线程没有超时策略,所以并不会自动关闭。所以我们在使用fixedThrePool核心线程时需要适当调用Shutdown方法,防止内存溢出。
- 可以自动关闭的是CachedThreadPool 线程。CachedThreadPool的线程keepAliveTime 默认为 60s ,核心线程数量为 0 ,所以不会有核心线程存活阻止线程池自动关闭。
synchronize和lock锁如何选择
在并发度低情况下使用 Synchronized ,这是因为,Synchronied 有一个锁升级的过程;
在要求中断,多个等待队列,可操作性性的,并发度高的情况下使用Lock锁;
常见线程同步工具,什么场景下使用
Semaphore
CountDownLatch
CyclicBarrier
Exchanger
Phaser
Semaphore 信号量是一类经典的同步工具。信号量通常用来限制线程可以同时访问的(物理或逻辑)资源数量。
CountDownLatch 一种非常简单、但很常用的同步辅助类。其作用是在完成一组正在其他线程中执行的操作之前,允许一个或多个线程一直阻塞。
CyclicBarrier 一种可重置的多路同步点,在某些并发编程场景很有用。它允许一组线程互相等待,直到到达某个公共的屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier在释放等待线程后可以重用,所以称它为循环的barrier。
Phaser一种可重用的同步屏障,功能上类似于CyclicBarrier和CountDownLatch,但使用上更为灵活。非常适用于在多线程环境下同步协调分阶段计算任务(Fork/Join框架中的子任务之间需同步时,优先使用Phaser)
Exchanger允许两个线程在某个汇合点交换对象,在某些管道设计时比较有用。Exchanger提供了一个同步点,在这个同步点,一对线程可以交换数据。每个线程通过exchange()方法的入口提供数据给他的伙伴线程,并接收他的伙伴线程提供的数据并返回。当两个线程通过Exchanger交换了对象,这个交换对于两个线程来说都是安全的。Exchanger可以认为是 SynchronousQueue 的双向形式,在运用到遗传算法和管道设计的应用中比较有用。
线程池原理
预创建技术,创建流程
一写多读 voliate,多写多读 cas
多次调用start()
Java的线程是不允许启动两次的,第二次调用必然会抛出IllegalThreadStateException,这是一种运行时异常
网友评论