java知识_Java知识整理

一. Java为何不支持多继承

1. 多继承是什么?

多继承:即一个子类可以同时继承多个基类,有多个父类,可以同时拥有多个父类的方法

2. 多继承有何优缺点?

多继承优点:扩展子类,使用更多的父类方法;

多继承缺点:当多个父类拥有相同的属性/方法时(且子类未进行重写时,重写后默认使用子类的方法),使用时会有歧义(不知该使用哪个父类属性/方法)。

3. Java为何不支持多继承?

相较于多继承的优点,它的缺点更为显著,因此Java只支持单继承,但是Java提供了办法可以实现多继承的功能。

4. 如果Java要实现多继承可以用什么办法?

Java中要实现多继承的功能,可以使用接口Interface:

接口与接口之间只能使用extends(继承),不能使用implements(实现)。

使用接口实现多继承例子:

//定义两个接口

public Interface interfaceA{

public void methodA();

}

//接口B继承接口A

public Interface interfaceB extends interfaceA{

public void methodB();

}

//定义实现类,实现接口B

public class classA implements interfaceB{

@Override

public void methodA() {

// TODO Auto-generated method stub

System.out.println("methodA");

}

@Override

public void methodB() {

System.out.println("methodB");

}

}

二. HashMap

参考文章:[https://blog.csdn.net/qq_42956048/article/details/91909184#HashMap__7]

1. HashMap是什么?

2. HashMap为什么是无序的?

与HashMap的Put方法有关,以下是put方法的实现顺序:

对数据的key值的hashcode进行Hash操作

根据hash值以及表长计算出在HashMap中的索引

查看索引地址是否有键值存在(即发生碰撞),若发生碰撞则遍历链表查看是否有相同key值存在,如存在,则覆盖其value,否则将其用链表方式链接在后(JDK8后,节点超过8个使用红黑树插入)

若未发生碰撞,则直接插入;

如map长度超过其扩容阈值(长度*扩容因子【默认0.75】)则先进行扩容,再进行插入;

null key的元素永远会放到index为0的链表里面

1408706e488da402ea86d1c2468b410e.png

put的过程可参见下图:

b672b739fac441a9c4bb4547a1365d94.png

三. 进程和线程相关知识(总结)

1. 进程和线程是什么

进程是资源分配的基本(最小)单位,有独立的内存单元。线程是执行调度的基本(最小)单位,共享内存资源。一个CPU至少有一个进程,一个进程至少有一个线程。线程可以说是进程的实体。

2. 进程和线程有什么区别

1.线程不能单独存在,必须依附于进程存在;

2.多线程程序中,一个线程死掉,整个进程就挂了,而进程不会有这种隐患,进程挂掉不会影响其他进程,因此多进程程序比多线程程序更为健壮,但进程切换的资源与效率比线程切换消耗更大;

3.线程之间通信比进程之间更快,更方便,因为他们共享静态变量、全局变量等。

3. 什么是线程安全?

当多个线程访问某个方法时,不管你通过怎样的调用方式、或者说这些线程如何交替地执行,我们在主程序中不需要去做任何的同步,这个类的结果行为都是我们设想的正确行为,那么我们就可以说这个类是线程安全的。

4. 如何保证线程安全?||synchronized和Volatile

synchronized

使用原因:synchronized是通过给当前对象(this)加锁。如,A线程正在访问方法P,使用synchronized会给P加上锁,线程B想访问P时必须先等待,进入等待状态,当A线程访问完毕后,再进场。这样保证了s的完整性synchronized保证了在多线程的环境下,数据的一致性。

如果多个线程共享一个对象,如果它们同时修改这个共享对象,这就产生了竞争现象。

此段内容参考: https://blog.csdn.net/csdnliu...

e.g 如下图所示,线程A和线程B共享一个对象obj。假设线程A从主存读取Obj.count变量到自己的CPU缓存,同时,线程B也读取了Obj.count变量到它的CPU缓存,并且这两个线程都对Obj.count做了加1操作。此时,Obj.count加1操作被执行了两次,不过都在不同的CPU缓存中。

eeb2754c7d29d42e9aeca0f10d653a16.png

但这种方法有个问题,就是当synchronized锁住一个对象后,别的进程如果想获取这个对象,必须等待当前线程执行完释放锁才可以,否则会一直处于等待状态。

注意点:虽然加synchronized关键字,可以让我们的线程变得安全,但是我们在用的时候,也要注意缩小synchronized的使用范围,如果随意使用时很影响程序的性能,别的对象想拿到锁,结果你没用锁还一直把锁占用,这样就有点浪费资源。

Volatile

由于线程需要使用一个变量对象时,先会将该变量拷贝到工作内存中,并且优先在工作内存中读取。因此可能会出现数据不一致的问题:

e.g 线程A读取变量a(a=1),将其拷贝到工作内存中,同时线程B也读取变量a并将其拷贝到工作内存中,A线程修改a(a=3;)在A线程将修改后的a放置在主存前,此时B线程也修改了a,但用过的不是A修改后的值(a=3)而是工作内存中的a(a=1),并对变量a进行了操作(a=a+1),此时就会出现数据不一致的问题。

0e6aefa882c7813d2980f58d04b06251.png

使用Volatile可以保证线程读取变量时,是从主存中读取的,并且对变量的更新也会直接写到主存,保证了线程间的可见性。

lock

lock是在jdk1.6之后提出的,与synchronized类似,但是他更具有操作性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值