关键字

volatile

Java的内存模型,线程执行时会将变量从主内存加载到线程工作内存,建立一个副本,在某个时刻写回。valatile修饰的变量每次都读取主内存的值,有更新则立即写回主内存。

“volatile保证了线程之间的可见性”:线程看到volatile变量会去读取主内存最新的值,修改也会直接写到主内存中,所以保证了valatile变量在各个线程间的可见性。

valatile保证了其他线程取当前变量中的值时 是所有线程中 最新的数据

一个volatile例子

 

synchronized

synchronized锁定的对象,类,语句在各线程之间是互斥的

当线程释放锁的时候,会将共享变量的值刷新到主内存中。

一个线程访问一个对象中的synchronized(this)同步代码块时,其他试图访问该对象的线程将被阻塞

非静态方法的同步锁与对象关联,不同对象拥有不同的锁

一个线程访问一个对象的synchronized代码块时,别的线程可以访问该对象的非synchronized代码块而不受阻塞。

作为关键字修饰方法,和在方法中添加同步锁的代码块作用相同,如下:

构造方法不能使用synchronized关键字,但可以使用synchronized代码块来进行同步。

若修饰静态方法,则同步锁止整个类,静态方法属于类,各个对象都经过这个锁。

synchronized关键字不能继承,子类中调用有锁父类方法则会同步执行。

synchronized关键字修饰类时synchronized(a.class),所有类对象共用一把锁。

如何使用 volatile, synchronized, final 进行线程间通信.

单例中和handlerThread中用了synchronized

 

synchronized原语和ReentrantLock在一般情况下没有什么区别,但是在非常复杂的同步应用中,请考虑使用ReentrantLock,特别是遇到下面2种需求的时候。

1.某个线程在等待一个锁的控制权的这段时间需要中断
2.需要分开处理一些wait-notify,ReentrantLock里面的Condition应用,能够控制notify哪个线程
3.具有公平锁功能,每个到来的线程都将排队等候

Java Synchronize 和 Lock 的区别与用法

 

final

初始化后不可改变,修饰数组时,数组的引用不可改变,但是数字的值可变。

final修饰的类不能被继承

 

static

静态变量在内存中只有一个拷贝,加载类的过程中完成静态变量的内存分配

static代码块是类加载时,初始化自动执行的

static方法可以直接通过类名调用,任何的实例也都可以调用,只能访问static的变量和方法。

 

public protected private

public 所有类可见

protected本包和所有子类可见

private仅本类可见

default本包可见

 

重写Override

  • 参数列表必须完全与被重写方法的相同;
  • 返回类型必须完全与被重写方法的返回类型相同;
  • 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为public,那么在子类中重写该方法就不能声明为protected。
  • 父类的成员方法只能被它的子类重写。
  • 声明为final的方法不能被重写。
  • 声明为static的方法不能被重写,但是能够被再次声明。
  • 子类和父类个包在同一中,那么子类可以重写父类所有方法,除了声明为private和final的方法。
  • 子类和父类不在同一个包中,那么子类只能够重写父类的声明为public和protected的非final方法。
  • 也就是子类只能重写可以从父类处继承的方法
  • 重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
  • 构造方法不能被重写。
  • 当需要在子类中调用父类的被重写方法时,要使用super关键字。

 

重载Overload

重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。

每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。

最常用的地方就是构造器的重载。

重载规则

  • 被重载的方法必须改变参数列表(参数个数或类型或顺序不一样);
  • 被重载的方法可以改变返回类型;
  • 被重载的方法可以改变访问修饰符;
  • 被重载的方法可以声明新的或更广的检查异常;
  • 方法能够在同一个类中或者在一个子类中被重载。
  • 无法以返回值类型作为重载函数的区分标准。

重写与重载之间的区别

重写是在之前方法的基础内 修改了方法的内容 替代的原方法

重载是增加了一个与之前不同的 可随意变化的方法

区别点重载方法重写方法
参数列表必须修改一定不能修改
返回类型可以修改一定不能修改
异常可以修改可以减少或删除,一定不能抛出新的或者更广的异常
访问可以修改一定不能做更严格的限制(可以降低限制)

 

 

虚拟方法

通过 父类引用调用子类对象 中 子类重写了父类的方法

 

抽象类、接口

作者:程序狗
链接:https://www.zhihu.com/question/20149818/answer/153188511
1、抽象类和接口都不能被 直接实例化
2、抽象类要被子类继承,接口要被子类实现。
3、接口里面只能对方法进行声明,抽象类既可以对方法进行声明也可以对方法进行实现。
4、抽象类里面的抽象方法必须全部被子类实现,如果子类不能全部实现,那么子类必须也是抽象类。接口里面的方法也必须全部被子类实现,如果子类不能实现那么子类必须是抽象类。

5、接口里面的方法只能声明,不能有具体的实现。这说明接口是设计的结果,抽象类是重构的结果。6、抽象类里面可以没有抽象方法。

7、如果一个类里面有抽象方法,那么这个类一定是抽象类。

8、抽象类中的方法都要被实现,所以抽象方法不能是静态的static,也不能是私有的private。

接口中方法默认为 public abstract 变量默认为 public static final

9、接口(类)可以继承接口,甚至可以继承多个接口。但是类只能继承一个类。

10、抽象级别(从高到低):接口>抽象类>实现类。

11、抽象类主要是用来抽象类别,接口主要是用来抽象方法功能。当你关注事物的本质的时候,请用抽象类;当你关注一种操作的时候,用接口。

12、抽象类的功能应该要远多于接口,但是定义抽象类的代价较高。因为高级语言一个类只能继承一个父类,即你在设计这个类的时候必须要抽象出所有这个类的子类所具有的共同属性和方法;但是类(接口)却可以继承多个接口,因此每个接口你只需要将特定的动作方法抽象到这个接口即可。也就是说,接口的设计具有更大的可扩展性,而抽象类的设计必须十分谨慎。

13、接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法

14、标记接口

 

 

进程 线程

进程和线程都是一个时间段的描述,是CPU工作时间段的描述。

只是粒度不同

CPU执行很快 需要准备好程序的执行环境 也就是上下文

进程包含系统资源,内存 相当于上下文

线程是共享上下文环境的更小的CPU时间段

进程间资源独立,线程间资源共享

1、进程是什么?
是具有一定独立功能的程序、它是系统进行资源分配和调度的一个独立单位,重点在系统调度和单独的单位,也就是说进程是可以独 立运行的一段程序。
2、线程又是什么?
线程进程的一个实体,是CPU调度和分派的基本单位,他是比进程更小的能独立运行的基本单位,线程自己基本上不拥有系统资源。
在运行时,只是暂用一些计数器、寄存器和栈 。二、他们之间的关系1、一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程(通常说的主线程)。
2、资源分配给进程,同一进程的所有线程共享该进程的所有资源。
3、线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。
4、处理机分给线程,即真正在处理机上运行的是线程。
5、线程是指进程内的一个执行单元,也是进程内的可调度实体。三、从三个角度来剖析二者之间的区别
1、调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位。
2、并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可以并发执行。
3、拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源。

线程状态

 1、新状态:线程对象已经创建,还没有在其上调用start()方法。

 2、可运行状态:当线程有资格运行,但调度程序还没有把它选定为运行线程时线程所处的状态。当start()方法调用时,线程首先进入可运行状态。在线程运行之后或者从阻塞、等待或睡眠状态回来后,也返回到可运行状态。

 3、运行状态:线程调度程序从可运行池中选择一个线程作为当前线程时线程所处的状态。这也是线程进入运行状态的唯一一种方式。

 4、等待/阻塞/睡眠状态:这是线程有资格运行时它所处的状态。实际上这个三状态组合为一种,其共同点是:线程仍旧是活的,但是当前没有条件运行。换句话说,它是可运行的,但是如果某件事件出现,他可能返回到可运行状态。

可能由于各种原因进入阻塞状态:
1>线程通过调用sleep方法进入睡眠状态;
2>线程调用一个在I/O上被阻塞的操作,即该操作在输入输出操作完成之前不会返回到它的调用者;
3>线程试图得到一个锁,而该锁正被其他线程持有;
4>线程在等待某个触发条件;

阻塞消除后回到可运行状态

 5、死亡态:当线程的run()方法完成时就认为它死去。这个线程对象也许是活的,但是,它已经不是一个单独执行的线程。线程一旦死亡,就不能复生。如果在一个死去的线程上调用start()方法,会抛出java.lang.IllegalThreadStateException异常。

原子性

synchronized 保证代码段原子性

可见性

一个线程修改了共享变量的值,其他线程能够立刻得知这个修改

synchronized  final  volatile

volatile 保证新值能立即刷新到主内存上  每次使用前在主内存上读取

同步块的可见性是由unlock前必须 store write  操作 获得的

而final的可见性  构造器一旦完成了初始化 那么在其他线程中就可以看见它

 

有序性

本线程内观察一切都是有序的

其他线程观察 都是无序的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值