现在的位置: 首页 > 综合 > 正文

Java基础知识大整理

2019年05月27日 ⁄ 综合 ⁄ 共 2219字 ⁄ 字号 评论关闭
Java并发包

锁机制:通过cas机制保证了当多线程并发时,就算所有的线程都同时访问,但是只会有一个成功,而锁的本质就是,只有一个能操作其他的都“睡觉”,当使用lock是,一定要注意lock与unlock的次数要相等

volatile机制:参考下面的例子,也就是说对volatile修饰的变量的修改不能依赖于当前的值,所以感觉volatile只能使用在标志位了

<span style="font-size:18px;">public class VolatileTest {
  public static volatile int i;
 
  public VolatileTest();
    Code:
       0: aload_0       
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return        
    LineNumberTable:
      line 1: 0
 
  public static void increase();
    Code:
       0: getstatic     #2                  // Field i:I, 把i的值取到了操作栈顶,volatile保证了i值此时是正确的. 
       3: iconst_1      
       4: iadd                              // increase,但其他线程此时可能已经把i值加大了好多
       5: putstatic     #2                  // Field i:I ,把这个已经out of date的i值同步回主内存中,i值被破坏了.
       8: return        
    LineNumberTable:
      line 6: 0
      line 7: 8
}</span>


原子变量:也是通过cas机制实现的,cas是什么:compare and swap就是线比较在修改


Thread

ThreadLocal:线程本地变量,或者说是线程的私有变量,这不是解决线程安全问题的解决方法,可以当作一个传值工具,但不建议这么做

public class ThreadLocalTest {

	static class ResourceClass {
		
		public final static ThreadLocal<String> RESOURCE_1 = new ThreadLocal<String>();
		
		public final static ThreadLocal<String> RESOURCE_2 = new ThreadLocal<String>();
		
	}
	
	static class A {
		
		public void setOne(String value) {
			ResourceClass.RESOURCE_1.set(value);
		}
		
		public void setTwo(String value) {
			ResourceClass.RESOURCE_2.set(value);
		}	
	}
	
	static class B {
		public void display() {
			System.out.println(ResourceClass.RESOURCE_1.get() + ":" + ResourceClass.RESOURCE_2.get());
		}
	}
	
	public static void main(String []args) {
		final A a = new A();
		final B b = new B();
		for(int i = 0 ; i < 15 ; i ++) {
			final String resouce1 = "线程-" + i, resouce2 = " value = (" + i + ")";
			new Thread() {  
                public void run() {  
                    try {  
                        a.setOne(resouce1);
                        a.setTwo(resouce2);
                        b.display();
                    }finally {  
                    	ResourceClass.RESOURCE_1.remove();
                    	ResourceClass.RESOURCE_2.remove();
                    }  
                }  
            }.start();
		}
	}
}

与此相对应的,就得说说unsafe类,在并发包的lock中的AQS就是使用的这个来使Thread挂起的


Java对象初始化

Java中的初始化顺序
对于静态变量、静态初始化块、变量、初始化块、构造器,它们的初始化顺序依次是
(静态变量、静态初始化块)>(变量、初始化块)> 构造器。
JAVA类首次装入时,会对静态成员变量或方法进行一次初始化,但方法不被调用是不会执行的,静态成员变量和静态初始化块级别相同,非静态成员变量和非静态初始化块级别相同。
初始化顺序:先初始化父类的静态代码--->初始化子类的静态代码-->
(创建实例时,如果不创建实例,则后面的不执行)初始化父类的非静态代码(变量定义等)--->初始化父类构造函数--->初始化子类非静态代码(变量定义等)--->初始化子类构造函数
类只有在使用New调用创建的时候才会被JAVA类装载器装入创建类实例时,首先按照父子继承关系进行初始化类实例创建时候,首先初始化块部分先执行,然后是构造方法;然后从本类继承的子类的初始化块执行,最后是子类的构造方法类消除时候,首先消除子类部分,再消除父类部分.
运行以上代码,我们会得到如下的输出结果: 
静态变量
静态初始化块
变量
初始化块
构造器

运行一下上面的代码:
父类--静态变量
父类--静态初始化块
子类--静态变量
子类--静态初始化块
父类--变量
父类--初始化块
父类--构造器
子类--变量
子类--初始化块
子类--构造器
说明:并不是父类完全初始化完毕后才进行子类的初始化,实际上子类的静态变量和静态初始化块的初始化是在父类的变量、初始化块和构造器初始化之前就完成了。
运行上面的代码,会得到如下的结果: 
Test--A
静态初始化块
Test--B



【上篇】
【下篇】

抱歉!评论已关闭.