java中关键字

  • 1 transient
    这个关键字一般会出现在实现Serializable的类中,作用是,当一个需要序列化的对象的某属性不想被序列化时,这个关键字就起作用了;举个例子,一个银行账户的信息,包含用户名,密码,卡号,等等,这里的密码一定是不想被序列化,或者是通过http传输的属性,那么就通过这个关键字,就可以实现,传输之后的信息不包含密码这一字段,代码例子:
package com.test.abc;

import java.io.*;

public class Account implements Serializable {
    private static final long serialVersionUID = 1L;
    private String userName;
    private transient String password;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }


    public static void main(String[] args) {
        Account account = new Account();
        account.setUserName("abc123");
        account.setPassword("552166");
        try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("E:/Account.txt"))){
            out.writeObject(account);
            out.flush();
        } catch (IOException e){
            e.printStackTrace();
        }


        try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("E:/Account.txt"))){
            Account obj = (Account) in.readObject();
            System.out.println(obj.getUserName());
            System.out.println(obj.getPassword());
        } catch (IOException | ClassNotFoundException e){
            e.printStackTrace();
        }
    }
}

输出的结果是

abc123
null

说明
(1)一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。
(2)transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。
(3)被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。
关于第三条需要说明一下,如果你试着写代码实现,会发现第三条没有得到证实,即反序列化之后的对象仍然可以得到被static修饰的属性,这是为什么呢?原因是,被static修饰的属性,是类属性,无论是怎么调用都会是有值得,但是如果做接口传输的话,相应收到的一定不会存在这个属性,你可以想象一下,生成的serialVersionUID一定不会在传输中体现出来,这是因为他本身是静态的类属性

  • 2 native
    什么是native?即JNI,全称叫 java native interface,相信大多数人第一次看到这个关键字都会是hashCode方法
    java平台有个用户和本地C语言交互的api,即java native interface
    Java code ———->JNI———–>C/C++ code
    由于某些场景,java并不适合或操作起来并不是那么简单,所以才使用了JNI调用本地方法,提高了java本身的效率

  • 3 volatile
    这个关键字对于经常做多线程的开发的人一定非常熟悉,我也是在网上找的相关资料进行整理的,有不对的地方希望指点一二;
    先说一下内存模型,程序在运行过程中的临时数据是存放在主内存(物理内存)中的,如果cpu执行写操作,那么会先从主内存中copy一份数据到cpu的高速缓存中,进行操作之后刷新到主内存中,这样在多线程中会出现一个场景,假如两个线程同时对同一个数据进行修改操作,他们先copy,此时copy的值是一样的,比如进行 i = i + 1的操作,线程1执行之后把结果刷新到内存中,但是这个结果跟线程2执行的结果是一样的,所以i=1,而不等于2,这样一定是不行的,所以有了以下解决方案:
    (1)对总线加LOCK#锁:由于cpu与其他组件的通信是通过总线实现的,如果对总线加锁,那么其他cpu就被阻塞了,这样做目的实现了,但是效率大大地减低了
    (2)通过缓存的一致性协议:著名的Intel MESI协议,
    再说并发编程的3要素

    • 1 原子性:对于这个特性我认为不需要解释什么,大家应该都知道,但是怎样的操作是原子性的呢?对于基本类型的读操作和写操作是原子性的,例子:
int x = 10;
int y = x;
y++;

这三个操作是原子性的么?只有第一个是原子性的,因为2中需要先进行x的读取,然后写入,3等价于y = y + 1 所以不是原子性的;那么针对大范围数据操作的原子性,就需要依赖于synchronize和lock来实现了,他们都实现了在同一时刻只能有一个线程直线当前代码块,保证原子性
- 2 可见性:多线程在访问同一变量时,某一线程对其进行修改,那么其他线程会第一时间看到修改后的值,那么可见性是由什么来保证的呢?就是咱们要说的volatile关键字了,他完成一件什么事:当共享资源被修改,他会立马刷新到内存中,其他线程会重新读取共享资源;同样synchronize和lock也是可以保证可见性的,因为共享资源修改之后下一个线程才能再次读取。
- 3 有序性:这里涉及到jvm的指令重排(Instruction Reorder),什么意思?jvm会在保证运行结果的正确性上重新对指令进行排序,举个例子:

int i = 0;   //1
boolean flag = false;  //2
i = 1;  //3
flag = false;  //4

上面的这段代码一定会按照1-2-3-4的顺序执行么?答案是不一定的,因为对于3,4,即使顺序变了,也不会影响之后的操作,再看下面的例子

int i = 0;  //1
int j = 10;  //2
i += 3;  //3
j *= i;  //4

上面这3,4的顺序能够变换么?当然不能,如果变了,那么直接会影响到程序最终的结果,这就是数据依赖,如果没有数据依赖,那么可以指令重排,否则不行;那么现在的问题就出现了,如果是多线程呢?

//线程1
context = getContext()
boolean flag = true;

//线程2
if (!flag){
    sleep();
}
doSomething(context)

对于线程1来说1,2本身没有数据依赖,可以进行重排,但是,如果先执行了2,那么线程2就会启动,直接调用了doSomething方法,参数context此时并没有初始化,会发生异常;所以指令重排对单线程是没有影响的,但是对于多线程而言,就不是很友好了;

重点来了
下面就来具体介绍下happens-before原则(先行发生原则):

程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作
锁定规则:一个unLock操作先行发生于后面对同一个锁额lock操作
volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作
传递规则:如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C
线程启动规则:Thread对象的start()方法先行发生于此线程的每个一个动作
线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生
线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行
对象终结规则:一个对象的初始化完成先行发生于他的finalize()方法的开始
原文这里写链接内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值