你知道Object中有哪些方法及其作用吗?
一、引言二、Object方法详解1.1、registerNatives()1.2、getClass()1.2.1、反射三种方式:1.3、hashCode()1.4、equals()1.4、clone()1.5、toString()1.6、wait()/ wait(long)/ waite(long,int)1.7、notify()/notifyAll()1.8、finalize()1.8.1、对象在内存中的状态1.8.2、垃圾回收机制1.8.3、强制垃圾回收三、总结
一、引言
Object是java所有类的基类,是整个类继承结构的顶端,也是最抽象的一个类。大家天天都在使用toString()、equals()、hashCode()、waite()、notify()、getClass()等方法,或许都没有意识到是Object的方法,也没有去看Object还有哪些方法以及思考为什么这些方法要放到Object中。本篇就每个方法具体功能、重写规则以及自己的一些理解。
二、Object方法详解
Object中含有:registerNatives()、getClass()、hashCode()、equals()、clone()、toString()、notify()、notifyAll()、wait(long)、wait(long,int)、wait()、finalize()共十二个方法。这个顺序是按照Object类中定义方法的顺序列举的,下面我也会按照这个顺序依次进行讲解。
1.1、registerNatives()
public class Object {
private static native void registerNatives();
static {
registerNatives();
}
}
什么鬼?哈哈哈,我刚看到这方法,一脸懵逼。从名字上理解,这个方法是注册native方法(本地方法,由JVM实现,底层是C/C++实现的)向谁注册呢?当然是向JVM,当有程序调用到native方法时,JVM才好去找到这些底层的方法进行调用。
Object中的native方法,并使用registerNatives()向JVM进行注册。(这属于JNI的范畴,9龙暂不了解,有兴趣的可自行查阅。)
static JNINativeMethod methods[] = {
{"hashCode", "()I", (void *)&JVM_IHashCode},
{"wait", "(J)V", (void *)&JVM_MonitorWait},
{"notify", "()V", (void *)&JVM_MonitorNotify},
{"notifyAll", "()V", (void *)&JVM_MonitorNotifyAll},
{"clone", "()Ljava/lang/Object;", (void *)&JVM_Clone},
};
为什么要使用静态方法,还要放到静态块中呢?
上一篇整理了类加载流程,我们知道了在类初始化的时候,会依次从父类到本类的类变量及类初始化块中的类变量及方法按照定义顺序放到< clinit>方法中,这样可以保证父类的类变量及方法的初始化一定先于子类。所以当子类调用相应native方法,比如计算hashCode时,一定可以保证能够调用到JVM的native方法。
1.2、getClass()
public final native Class getClass():这是一个public的方法,我们可以直接通过对象调用。
类加载的第一阶段类的加载就是将.class文件加载到内存,并生成一个java.lang.Class对象的过程。getClass()方法就是获取这个对象,这是当前类的对象在运行时类的所有信息的集合。这个方法是反射三种方式之一。
1.2.1、反射三种方式:
- 对象的getClass();
- 类名.class;
- Class.forName();
class extends ObjectTest {
private void privateTest(String str) {
System.out.println(str);
}
public void say(String str) {
System.out.println(str);
}
}
public class ObjectTest {
public static void main(String[] args) throws Exception {
ObjectTest = new ();
//获取对象运行的Class对象
Class<? extends ObjectTest> aClass = .getClass();
System.out.println(aClass);
//getDeclaredMethod这个方法可以获取所有的方法,包括私有方法
Method privateTest = aClass.getDeclaredMethod("privateTest", String.class);
//取消java访问修饰符限制。
privateTest.setAccessible(true);
privateTest.invoke(aClass.newInstance(), "private method test");
//getMethod只能获取public方法
Method say = aClass.getMethod("say", String.class);
say.invoke(aClass.newInstance(), "Hello World");
}
}
//输出结果:
//class test.
//private method test
//Hello World
反射主要用来获取运行时的信息,可以将java这种静态语言动态化,可以在编写代码时将一个子对象赋值给父类的一个引用,在运行时通过反射可以或许运行时对象的所有信息,即多态的体现。对于反射知识还是很多的,这里就不展开讲了。
1.3、hashCode()
public native int hashCode(); 这是一个public的方法,所以子类可以重写它。这个方法返回当前对象的hashCode值,这个值是一个整数范围内的(-2^31 ~ 2^31 - 1)数字。
对于hashCode有以下几点约束
- 在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改;
- 如果两个对象 x.equals(y) 方法返回true,则x、y这两个对象的hashCode必须相等。
- 如果两个对象x.equals(y) 方法返回false,则x、y这两个对象的hashCode可以相等也可以不等。但是,为不相等的对象生成不同整数结果可以提高哈希表的性能。
- 默认的hashCode是将内存地址转换为的hash值,重写过后就是自定义的计算方式;也可以通过System.identityHashCode(Object)来返回原本的hashCode。
public class HashCodeTest {
private int age;
private String name;
@Override
public int hashCode() {
Object[] a = Stream.of(age, name).toArray();
int result = 1;
for (Object element : a) {
result = 31 * result + (element == null ? 0 : element.hashCode());
}
return result;
}
}
推荐使用Objects.hash(Object… values)方法。相信看源码的时候,都看到计算hashCode都使用了31作为基础乘数,为什么使用31呢?我比较赞同与理解result * 31 = (result<<5) - result。JVM底层可以自动做优化为位运算,效率很高;还有因为31计算的hashCode冲突较少,利于hash桶位的分布。
1.4、equals()
public boolean equals(Object obj);用于比较当前对象与目标对象是否相等,默认是比较引用是否指向同一对象。为public方法,子类可重写。
public class Object{
public boolean equals(Object obj) {
return (this == obj);
}
}
为什么需要重写equals方法?
因为如果不重写equals方法,当将自定义对象放到map或者set中时;如果这时两个对象的hashCode相同,就会调用equals方法进行比较,这个时候会调用Object中默认的equals方法,而默认的equals方法只是比较了两个对象的引用是否指向了同一个对象,显然大多数时候都不会指向,这样就会将重复对象存入map或者set中。这就破坏了map与set不能存储重复对象的特性,会造成内存溢出。
重写equals方法的几条约定:
- 自反性:即x.equals(x)返回true,x不为null;
- 对称性:即x.equals(y)与y.equals(x)的结果相同,x与y不为null;
- 传递性:即x.equals(y)结果为true, y.equals(z)结果为true,则x.equals(z)结果也必须为true;
- 一致性:即x.equals(y)返回true或false,在未更改equals方法使用的参数条件下,多次调用返回的结果也必须一致。x与y不为null。
- 如果x不为null, x.equals(null)返回false。
我们根据上述规则来重写equals方法。
public class EqualsTest{
private int age;
private String name;
//省略get、set、构造函数等
@Override
public boolean equals(Object o) {
//先判断是否为同一对象
if (this == o) {
return true;
}
//再判断目标对象是否是当前类及子类的实例对象
//注意:instanceof包括了判断为null的情况,如果o为null,则返回false
if (!(o instanceof )) {
return false;
}
that = () o;
return age == that.age &&
Objects.equals(name, that.name);
}
public static void main(String[] args) throws Exception {
EqualsTest1 equalsTest1 = new EqualsTest1(23, "9龙");
EqualsTest1 equalsTest12 = new EqualsTest1(23, "9龙");
EqualsTest1 equalsTest13 = new EqualsTest1(23, "9龙");
System.out.println("-----------自反性----------");
System.out.println(equalsTest1.equals(equalsTest1));
System.out.println("-----------对称性----------");
System.out.println(equalsTest12.equals(equalsTest1));
System.out.println(equalsTest1.equals(equalsTest12));
System.out.println("-----------传递性----------");
System.out.println(equalsTest1.equals(equalsTest12));
System.out.println(equalsTest12.equals(equalsTest13));
System.out.println(equalsTest1.equals(equalsTest13));
System.out.println("-----------一致性----------");
System.out.println(equalsTest1.equals(equalsTest12));
System.out.println(equalsTest1.equals(equalsTest12));
System.out.println("-----目标对象为null情况----");
System.out.println(equalsTest1.equals(null));
}
}
//输出结果
//-----------自反性----------
//true
//-----------对称性----------
//true
//true
//-----------传递性----------
//true
//true
//true
//-----------一致性----------
//true
//true
//-----目标对象为null情况----
//false
从以上输出结果验证了我们的重写规定是正确的。
注意:instanceof 关键字已经帮我们做了目标对象为null返回false,我们就不用再去显示判断了。
建议equals及hashCode两个方法,需要重写时,两个都要重写,一般都是将自定义对象放至Set中,或者Map中的key时,需要重写这两个方法。
1.4、clone()
protected native Object clone() throws CloneNotSupportedException;
此方法返回当前对象的一个副本。
这是一个protected方法,提供给子类重写。但需要实现Cloneable接口,这是一个标记接口,如果没有实现,当调用object.clone()方法,会抛出CloneNotSupportedException。
public class CloneTest implements Cloneable {
private int age;
private String name;
//省略get、set、构造函数等
@Override
protected CloneTest clone() throws CloneNotSupportedException {
return (CloneTest) super.clone();
}
public static void main(String[] args) throws CloneNotSupportedException {
CloneTest cloneTest = new CloneTest(23, "9龙");
CloneTest clone = cloneTest.clone();
System.out.println(clone == cloneTest);
System.out.println(cloneTest.getAge()==clone.getAge());
System.out.println(cloneTest.getName()==clone.getName());
}
}
//输出结果
//false
//true
//true
从输出我们看见,clone的对象是一个新的对象;但原对象与clone对象的String类型的name却是同一个引用,这表明,super.clone方法对成员变量如果是引用类型,进行是浅拷贝。
那什么是浅拷贝?对应的深拷贝?
浅拷贝:拷贝的是引用。
深拷贝:新开辟内存空间,进行值拷贝。
那如果我们要进行深拷贝怎么办呢?看下面的例子。
class Person implements Cloneable{
private int age;
private String name;
//省略get、set、构造函数等
@Override
protected Person clone() throws CloneNotSupportedException {
Person person = (Person) super.clone();
//name通过new开辟内存空间
person.name = new String(name);
return person;
}
}
public class CloneTest implements Cloneable {
private int age;
private String name;
//增加了person成员变量
private Person person;
//省略get、set、构造函数等
@Override
protected CloneTest clone() throws CloneNotSupportedException {
CloneTest clone = (CloneTest) super.clone();
clone.person = person.clone();
return clone;
}
public static void main(String[] args) throws CloneNotSupportedException {
CloneTest cloneTest = new CloneTest(23, "9龙");
Person person = new Person(22, "路飞");
cloneTest.setPerson(person);
CloneTest clone = cloneTest.clone();
System.out.println(clone == cloneTest);
System.out.println(cloneTest.getAge() == clone.getAge());
System.out.println(cloneTest.getName() == clone.getName());
Person clonePerson = clone.getPerson();
System.out.println(person == clonePerson);
System.out.println(person.getName() == clonePerson.getName());
}
}
//输出结果
//false
//true
//true
//false
//false
可以看到,即使成员变量是引用类型,我们也实现了深拷贝。如果成员变量是引用类型,想实现深拷贝,则成员变量也要实现Cloneable接口,重写clone方法。
1.5、toString()
public String toString();这是一个public方法,子类可重写,建议所有子类都重写toString方法,默认的toString方法,只是将当前类的全限定性类名+@+十六进制的hashCode值。
public class Object{
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
}
我们思考一下为什么需要toString方法?
我这么理解的,返回当前对象的字符串表示,可以将其打印方便查看对象的信息,方便记录日志信息提供调试。
我们可以选择需要表示的重要信息重写到toString方法中。为什么Object的toString方法只记录类名跟内存地址呢?因为Object没有其他信息了,哈哈哈。
1.6、wait()/ wait(long)/ waite(long,int)
这三个方法是用来线程间通信用的,作用是阻塞当前线程,等待其他线程调用notify()/notifyAll()方法将其唤醒。这些方法都是public final的,不可被重写。
注意:
- 此方法只能在当前线程获取到对象的锁监视器之后才能调用,否则会抛出IllegalMonitorStateException异常。
- 调用wait方法,线程会将锁监视器进行释放;而Thread.sleep,Thread.yield()并不会释放锁。
- wait方法会一直阻塞,直到其他线程调用当前对象的notify()/notifyAll()方法将其唤醒;而wait(long)是等待给定超时时间内(单位毫秒),如果还没有调用notify()/nofiyAll()会自动唤醒;waite(long,int)如果第二个参数大于0并且小于999999,则第一个参数+1作为超时时间;
public final void wait() throws InterruptedException {
wait(0);
}
public final native void wait(long timeout) throws InterruptedException;
public final void wait(long timeout, int nanos) throws InterruptedException {
if (timeout < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos > 0) {
timeout++;
}
wait(timeout);
}
1.7、notify()/notifyAll()
前面说了,如果当前线程获得了当前对象锁,调用wait方法,将锁释放并阻塞;这时另一个线程获取到了此对象锁,并调用此对象的notify()/notifyAll()方法将之前的线程唤醒。这些方法都是public final的,不可被重写。
public final native void notify(); 随机唤醒之前在当前对象上调用wait方法的一个线程
public final native void notifyAll(); 唤醒所有之前在当前对象上调用wait方法的线程
下面我们使用wait()、notify()展示线程间通信。假设9龙有一个账户,只要9龙一发工资,就被女朋友给取走了。
//账户
public class Account {
private String accountNo;
private double balance;
private boolean flag = false;
public Account() {
}
public Account(String accountNo, double balance) {
this.accountNo = accountNo;
this.balance = balance;
}
/**
* 取钱方法
*
* @param drawAmount 取款金额
*/
public synchronized void draw(double drawAmount) {
try {
if (!flag) {
//如果flag为false,表明账户还没有存入钱,取钱方法阻塞
wait();
} else {
//执行取钱操作
System.out.println(Thread.currentThread().getName() + " 取钱" + drawAmount);
balance -= drawAmount;
//标识账户已没钱
flag = false;
//唤醒其他线程
notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void deposit(double depositAmount) {
try {
if (flag) {
//如果flag为true,表明账户已经存入钱,取钱方法阻塞
wait();
} else {
//存钱操作
System.out.println(Thread.currentThread().getName() + " 存钱" + depositAmount);
balance += depositAmount;
//标识账户已存入钱
flag = true;
//唤醒其他线程
notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//取钱者
public class DrawThread extends Thread {
private Account account;
private double drawAmount;
public DrawThread(String name, Account account, double drawAmount) {
super(name);
this.account = account;
this.drawAmount = drawAmount;
}
@Override
public void run() {
//循环6次取钱
for (int i = 0; i < 6; i++) {
account.draw(drawAmount);
}
}
}
//存钱者
public class DepositThread extends Thread {
private Account account;
private double depositAmount;
public DepositThread(String name, Account account, double depositAmount) {
super(name);
this.account = account;
this.depositAmount = depositAmount;
}
@Override
public void run() {
//循环6次存钱操作
for (int i = 0; i < 6; i++) {
account.deposit(depositAmount);
}
}
}
//测试
public class DrawTest {
public static void main(String[] args) {
Account brady = new Account("9龙", 0);
new DrawThread("女票", brady, 10).start();
new DepositThread("公司", brady, 10).start();
}
}
//输出结果
//公司 存钱10.0
//女票 取钱10.0
//公司 存钱10.0
//女票 取钱10.0
//公司 存钱10.0
//女票 取钱10.0
例子中我们通过一个boolean变量来判断账户是否有钱,当取钱线程来判断如果账户没钱,就会调用wait方法将此线程进行阻塞;这时候存钱线程判断到账户没钱, 就会将钱存入账户,并且调用notify()方法通知被阻塞的线程,并更改标志;取钱线程收到通知后,再次获取到cpu的调度就可以进行取钱。反复更改标志,通过调用wait与notify()进行线程间通信。实际中我们会时候生产者消费者队列会更简单。
注意:调用notify()后,阻塞线程被唤醒,可以参与锁的竞争,但可能调用notify()方法的线程还要继续做其他事,锁并未释放,所以我们看到的结果是,无论notify()是在方法一开始调用,还是最后调用,阻塞线程都要等待当前线程结束才能开始。
为什么wait()/notify()方法要放到Object中呢?
因为每个对象都可以成为锁监视器对象,所以放到Object中,可以直接使用。
1.8、finalize()
protected void finalize() throws Throwable ;
此方法是在垃圾回收之前,JVM会调用此方法来清理资源。此方法可能会将对象重新置为可达状态,导致JVM无法进行垃圾回收。
我们知道java相对于C++很大的优势是程序员不用手动管理内存,内存由jvm管理;如果我们的引用对象在堆中没有引用指向他们时,当内存不足时,JVM会自动将这些对象进行回收释放内存,这就是我们常说的垃圾回收。但垃圾回收没有讲述的这么简单。
finalize()方法具有如下4个特点:
- 永远不要主动调用某个对象的finalize()方法,该方法由垃圾回收机制自己调用;
- finalize()何时被调用,是否被调用具有不确定性;
- 当JVM执行可恢复对象的finalize()可能会将此对象重新变为可达状态;
- 当JVM执行finalize()方法时出现异常,垃圾回收机制不会报告异常,程序继续执行。
public class FinalizeTest {
private static FinalizeTest ft = null;
public void info(){
System.out.println("测试资源清理得finalize方法");
}
public static void main(String[] args) {
//创建FinalizeTest对象立即进入可恢复状态
new FinalizeTest();
//通知系统进行垃圾回收
System.gc();
//强制回收机制调用可恢复对象的finalize()方法
// Runtime.getRuntime().runFinalization();
System.runFinalization();
ft.info();
}
@Override
public void finalize(){
//让ft引用到试图回收的可恢复对象,即可恢复对象重新变成可达
ft = this;
throw new RuntimeException("出异常了,你管不管啊");
}
}
//输出结果
//测试资源清理得finalize方法
我们看到,finalize()方法将可恢复对象置为了可达对象,并且在finalize中抛出异常,都没有任何信息,被忽略了。
1.8.1、对象在内存中的状态
对象在内存中存在三种状态:
- 可达状态:有引用指向,这种对象为可达状态;
- 可恢复状态:失去引用,这种对象称为可恢复状态;垃圾回收机制开始回收时,回调用可恢复状态对象的finalize()方法(如果此方法让此对象重新获得引用,就会变为可达状态,否则,会变为不可大状态)。
- 不可达状态:彻底失去引用,这种状态称为不可达状态,如果垃圾回收机制这时开始回收,就会将这种状态的对象回收掉。
1.8.2、垃圾回收机制
- 垃圾回收机制只负责回收堆内存种的对象,不会回收任何物理资源(例如数据库连接、网络IO等资源);
- 程序无法精确控制垃圾回收的运行,垃圾回收只会在合适的时候进行。当对象为不可达状态时,系统会在合适的时候回收它的内存。
- 在垃圾回收机制回收任何对象之前,总会先调用它的finalize()方法,该方法可能会将对象置为可达状态,导致垃圾回收机制取消回收。
1.8.3、强制垃圾回收
上面我们已经说了,当对象失去引用时,会变为可恢复状态,但垃圾回收机制什么时候运行,什么时候调用finalize方法无法知道。虽然垃圾回收机制无法精准控制,但java还是提供了方法可以建议JVM进行垃圾回收,至于是否回收,这取决于虚拟机。但似乎可以看到一些效果。
public class GcTest {
public static void main(String[] args){
for(int i=0;i<4;i++){
//没有引用指向这些对象,所以为可恢复状态
new GcTest();
//强制JVM进行垃圾回收(这只是建议JVM)
System.gc();
//Runtime.getRuntime().gc();
}
}
@Override
public void finalize(){
System.out.println("系统正在清理GcTest资源。。。。");
}
}
//输出结果
//系统正在清理GcTest资源。。。。
//系统正在清理GcTest资源。。。。
System.gc(),Runtime.getRuntime().gc()两个方法作用一样的,都是建议JVM垃圾回收,但不一定回收,多运行几次,结果可能都不一致。
三、总结
本篇举例讲解了Objec中的所有方法的作用、意义及使用,从java最基础的类出发,感受java设计之美吧。我是不会高诉大家,这好像面试也会问的【摊手】。
整理不易,觉得可以,希望大家点赞支持啊。转载请注明出处。
十分感谢以下链接的分享,参考链接:
你知道Object中有哪些方法及其作用吗?的更多相关文章
- Object中有哪些方法及其作用
你知道Object中有哪些方法及其作用吗? 一.引言 二.Object方法详解 1.1.registerNatives() 1.2.getClass() 1.2.1.反射三种方式: 1.3.hashC ...
- Object中有哪些方法?
有一种遗憾就是,每天都见到你,但是却不关注你!等到面试的时候才后悔莫及. Object类中有9大public方法: equals:判断两个对象"相等" hashCode:获取对象的 ...
- Object中的方法以及对象相等的判定
看图说话 Object有以下几个方法 getClass() final类型,主要是用来获得运行时的类型 hashCode() 返回该对象的哈希码值,方法是为了提高哈希表(例如 java.util.Ha ...
- Object中有哪些公共方法及作用
大家在学习java的时候,一定遇到过Object类,因为在java单一继承体系中Object类是根类,所有的类都会继承它,并拥有Object的公共方法,意味着在java的面向对象的世界中,所有对象都拥 ...
- Java温故而知新(7)Object类及其方法讲解
一.java.lang.Object java.lang包在使用的时候无需显示导入,编译时由编译器自动导入. Object类是类层次结构的根,Java中所有的类从根本上都继承自这个类. Object类 ...
- 方法object面试题分析:7JAVA中Object的clone方法详解-克隆-深克隆
时间紧张,先记一笔,后续优化与完善. 每日一道理 翻开早已发黄的页张,试着寻找过去所留下的点点滴滴的足迹.多年前的好友似乎现在看来已变得陌生,匆忙之间,让这维持了多年的友谊变淡,找不出什么亲切 ...
- List集合去除重复对象及equals()、hashCode()方法的作用
原文:https://blog.csdn.net/freelander_j/article/details/52211010 在java中,要将一个集合中重复的对象除去,如果这个集合中的数据类型是基本 ...
- 自己(转)JAVA中toString方法的作用
JAVA中toString方法的作用 因为它是Object里面已经有了的方法,而所有类都是继承Object,所以“所有对象都有这个方法”. 它通常只是为了方便输出,比如System.out.print ...
- 面向对象编程(四)继承,概念及super关键字,final关键字,Object类常见方法
继承 概念: ① 继承背后的思想就是基于已存在的类来构建新类; ② 当从已存在类继承时,就重用了它的方法和属性,还可以添加新的方法和属性来定制新类以应对需求; ③ 当从其它类导出的类叫作子 ...
随机推荐
- window10 蓝牙怎么连接音响或蓝牙耳机
window10 蓝牙怎么连接音响或蓝牙耳机 1.在电脑上依次点击win图标右键-->设置,打开系统设置窗口. 2.点击“设备”,在窗口左侧选择“蓝牙”,右侧检查并开启电脑的蓝牙设备开关, 3. ...
- MQ选型对比ActiveMQ,RabbitMQ,RocketMQ,Kafka 消息队列框架选哪个?
最近研究消息队列,发现好几个框架,搜罗一下进行对比,说一下选型说明: 1)中小型软件公司,建议选RabbitMQ.一方面,erlang语言天生具备高并发的特性,而且他的管理界面用起来十分方便.不考虑r ...
- iframe子元素无法全屏
最近做的项目中遇到的问题: 在最新的Chrome浏览器中,全屏功能正常 在旧版本Chrome浏览器中(与最新版版本号相差二十左右),全屏功能无效 在IE11浏览器中,全屏功能无效 反复排查,发现该项目 ...
- 技能篇丨FineCMS 5.0.10 多个漏洞详细分析
今天是一篇关于技能提升的文章,文章中的CMS是FineCMS,版本是5.0.10版本的几个漏洞分析,主要内容是介绍漏洞修补前和修补后的分析过程,帮助大家快速掌握该技能. 注:篇幅较长,阅读用时约7分钟 ...
- xml路径错误无法打包
http://blog.csdn.net/iangelfalls/article/details/7102844
- long类型在内存中占8个字节,float类型在内存中占4个字节,为什么long还要比float小呢?
结论:数值范围大小和占用的字节没有关系. float类型的范围: 负数:-3.402823E38~-1.401298E-45 整数:0 正数:1.401298E-45~3.402823E38 long ...
- 深入解读Linux进程调度Schedule【转】
转自:https://blog.csdn.net/Vince_/article/details/88982802 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文 ...
- URL 路由系统 + views 函数
一.URL URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表:你就是以这种方式告诉Django,对于这个URL调用这段 ...
- 09、日志轮转+rsync同步
logrotate - rotates, compresses, and mails system logs 日志轮转 rotate 日志切割 轮转 切割 备份 归档 常见 ...
- Docker介绍及安装(一)
一.Docker简介 1.1 docker介绍 Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核的cgroup,namespace,以及 AUFS 类的 ...