Java中常用但容易忽略的知识点

xiaoxiao2021-02-28  9

1.并发编程的几种特性:可见性,有序性,原子性

1.1 原子性

原子性是指一个操作是不可中断的,要么全部执行成功要么全部执行失败,有着“同生共死”的感觉。及时在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程所干扰。 如果一个操作是原子性的,那么在多线程环境下, 就不会出现变量被修改等奇怪的问题。 原子性解释2:原子是世界上的最小单位,具有不可分割性。 比如 a=0;(a非long和double类型) 这个操作是不可分割的,那么我们说这个操作时原子操作。 再比如:a++; 这个操作实际是a = a + 1;是可分割的,所以他不是一个原子操作。 非原子操作都会存在线程安全问题,需要我们使用同步技术(sychronized)来让它变成一个原子操作。 一个操作是原子操作,那么我们称它具有原子性。 Java的concurrent包下提供了一些原子类,我们可以通过阅读API来了解这些原子类的用法。比如:AtomicInteger、AtomicLong、AtomicReference等。

1.2 有序性 synchronized

synchronized语义表示锁在同一时刻只能由一个线程进行获取,当锁被占用后,其他线程只能等待。因此,synchronized语义就要求线程在访问读写共享变量时只能“串行”执行,因此synchronized具有有序性。

1.3. 可见性

可见性是指当一个线程修改了共享变量后,其他线程能够立即得知这个修改。通过之前对synchronzed内存语义进行了分析,当线程获取锁时会从主内存中获取共享变量的最新值,释放锁的时候会将共享变量同步到主内存中。从而,synchronized具有可见性。同样的在volatile分析中,会通过在指令中添加lock指令,以实现内存可见性。

参考链接:https://www.jianshu.com/p/cf57726e77f2

Volatile ===========

Volatile是轻量级的synchronized,它在多处理器开发中保证了共享变量的“可见性”。可见性的意思是当一个线程修改一个共享变量时,另外一个线程能读到这个修改的值。 volatile 只提供了保证访问该变量,每一次读取改变量的时候都是从内存中读取,并不会使用寄存器缓存该值。 对该变量的修改,volatile 并不提供原子性的保证;

synchronized的同步作用不仅保证了对同一个锁线程的互斥,还保证了数据的同步。 volatile在某些情况下比synchronized的开销更小,应用场景是首先要确认该共享变量是否会被频繁的写。

volatile对比synchronized

两者修饰的不同,volatile修饰的是变量,synchronized修饰的是方法和代码块 两者的功能不同。volatile保证数据的可见性,synchronized是线程同步执行(间接保证数据可见性,让线程工作内存的变量和公共内存的同步) volatile性能比synchronized性能高

一个简单的单例模式

public class Singleton { private Singleton() { } private volatile static Singleton instance; public Singleton getInstance(){ if(instance==null){ synchronized (Singleton.class){ if(instance==null){ instance = new Singleton(); } } } return instance; } }

参考链接: https://www.cnblogs.com/-new/p/7190092.html http://www.infoq.com/cn/articles/ftf-java-volatile# http://blog.csdn.net/mr_smile2014/article/details/49746479 https://www.jianshu.com/p/cf57726e77f2

WeakRefrence == WeakReference 弱引用可以让您保持对对象的引用,同时允许GC在必要时释放对象,回收内存。对于那些创建便宜但耗费大量内存的对象,即希望保持该对象,又要在应用程序需要时使用,同时希望GC必要时回收时,可以考虑使用弱引用。 WeakReference的一个特点是它何时被回收是不可确定的, 因为这是由GC运行的不确定性所确定的. 所以, 一般用weak reference引用的对象是有价值被cache, 而且很容易被重新被构建, 且很消耗内存的对象.

3.1 除了弱引用,还有软引用。

SoftReference(软引用)和WeakReference的区别在于,假如下次GC的时候,发现内存没有溢出,则不会回收SoftReference关联的对象,但是对于WeakReference,在下一次GC的时候,一定会回收,无论内存是否满。像缓存,其实最适合的个人认为应该是SoftReference,因为缓存里面的数据是运行时会用到的,能不回收就尽量不要去回收它们,而等到内存实在不够的时候再去回收。

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

弱应用也不是在GC时一定会被回收,仅当引用到的变量全部都可回收后,才可回收。 弱引用是配合强引用一起使用的,不是单独使用。 错误示例:

WeakReference ref = new WeakReference(new Object())

当你创建出来一个弱引用的时候,这个弱引用对应的对象可能很快就被释放了,因为没有强引用指向它

实际上弱引用是这样用的

WeakReference ref;//这里一般是成员变量之类的,用于缓存 逻辑代码 Object obj = null; if(ref != null) obj = ref.get(); //先取缓存对象 if(obj == null){ //如果没有缓存对象就创建一个,同时存到缓存里面去 obj = new Object(); ref = new WeakReference(obj); } //其它业务逻辑 obj......

3.2 引用队列(ReferenceQueue)

弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。WeakReference的父类Reference中有一个变量queue,是ReferenceQueue类型的。WeakReference中的构造函数中有一个两个参数的构造函数,其中第二个参数就是这个ReferenceQueue,表示在WeakReference指向的对象被回收之后,可以利用ReferenceQueue来保存被回收的对象。

4. Java线程池ExecutorService

Java通过Executors提供四种线程池,分别为: newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。 newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。 newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。 现行大多数GUI程序都是单线程的。Android中单线程可用于数据库操作,文件操作,应用批量安装,应用批量删除等不适合并发但可能IO阻塞性及影响UI线程响应的操作。

参考链接: http://www.cnblogs.com/-new/p/7358255.html https://www.cnblogs.com/Steven0805/p/6393443.html https://www.cnblogs.com/zhaoyan001/p/7049627.html

5. heap是堆,stack是栈

6. 基本数据类型

http://www.runoob.com/java/java-basic-datatypes.html

转载请注明原文地址: https://www.6miu.com/read-2150043.html

最新回复(0)