static,synchronized,final这几个词的理解

虽然好几次学习了这三个,但是过了一段时间就又忘记了,决定总结一下,有错误留言一起讨论哟

static

1、static修饰类

static是不能修饰public所修饰的类的,但是可以有静态内部类,例如:

public class TestStatic {

    public static class innerClassStatic{
        public innerClassStatic() {
            // TODO Auto-generated constructor stub
            System.out.println("静态内部类调用----");
        }
        public static String getNumber(){
            return "2";
        }
        public String getNumberTwo(){
            System.out.println(innerClassStatic.getNumber());
            return "aa";
        }
    }
    public void getNumberOpt(){
        //静态内部类只能通过类名调用
        //新建一个静态内部类对象调用非静态方法
        System.out.println(new TestStatic.innerClassStatic().getNumberTwo());
        System.out.println("-----------------------------------------------");
        //下面方法最好不要用,尽可能只在静态方法中调用  
        System.out.println(new TestStatic.innerClassStatic().getNumber());
        System.out.println("-----------------------------------------------");
        System.out.println(TestStatic.innerClassStatic.getNumber());
        System.out.println("-----------------------------------------------");

        //第一句话的调用结果是:
//      2
//      静态内部类调用----
//      2

    }
    /**
     * 静态方法
     * @param args
     */
    public static void main(String[] args) {
        System.out.println("1-----------------------------------------------");
        System.out.println(TestStatic.innerClassStatic.getNumber());
        System.out.println("2-----------------------------------------------");
        System.out.println(new TestStatic.innerClassStatic().getNumberTwo());
        System.out.println("3-----------------------------------------------");
        new TestStatic().getNumberOpt();
    }
    /**
     * 调用结果是:
        第1步-----------------------------------------------
        2
        第2步-----------------------------------------------
        静态内部类调用----
        2
        aa
        第3步-----------------------------------------------
        静态内部类调用----
        2
        aa
        -----------------------------------------------
        静态内部类调用----
        2
        -----------------------------------------------
        2
        -----------------------------------------------
     */
}
2、static静态块与修饰变量和方法
public class TestStatic {
    //不可以被外部类调用,只能通过类方法调用
    private static int a=1;
    public static int b=3;
    static{
        System.out.println("static静态块");
        a++;
        b++;
    }
    public TestStatic() {
        // TODO Auto-generated constructor stub
        System.out.println("构造方法");
        a++;
    }
    public static void testN(){
        System.out.println("静态方法");
        a++;
        b++;
    }
    public void testNTwo(){
        System.out.println("非静态方法");
    }
}
public class TestStaticTwo {

    public static void main(String[] args) {
        System.out.println("----第一步----");
        TestStatic.testN();
        System.out.println("----第二步----");
        TestStatic testStatic=new TestStatic();
        testStatic.testNTwo();
        System.out.println("----第三步----");
        System.out.println(TestStatic.b+"@@");
    }
    /**
     * 结果:
        ----第一步----
        static静态块
        静态方法
        ----第二步----
        构造方法
        非静态方法
        ----第三步----
        5@@
     */
}

1、可见 静态块在全过程之中,只有在加载类的时候加载一次,其他时候都不会调用了
2、static修饰的变量从始至终只有一个存储的空间,不会随着对象的改变而改变
3、static修饰的方法或者静态块中只能够访问静态的变量或者方法

final

这个我在网上看到一个比较精辟的话,就是:
修饰变量:为常量,值不能改变
修饰对象:值能够改变,而引用不能改
修饰方法:不能够重写
修饰类:不可以被继承

synchronized

1、synchronized的同步锁是this对象(当前对象)

1.1 同步方法

public class TestThread {

    //synchronized的同步锁是this对象(类的对象)

    //1、修饰类
    public synchronized void syschronThread1(){
        System.out.println("当前调用synchronThread1方法的线程是:"+Thread.currentThread().getName());
        for(int i=0;i<5;i++){
            System.out.println("这是syschronThread1方法执行的同步方法,"+i);
        }
    }

    public static void main(String[] args) {
        final TestThread testThread=new TestThread();
        //测试1 syschronThread1
        Thread t1=new Thread(new Runnable() {

            public void run() {
                // TODO Auto-generated method stub
                testThread.syschronThread1();
            }
        },"thread1");
        /*t1.setName("");*/
        Thread t2=new Thread(new Runnable(){

            public void run() {
                // TODO Auto-generated method stub
                testThread.syschronThread1();
            }

        },"thread2");
        //使用start方法名称就对了,使用run方法名称就是main
        //原因是:
        //区别:调用start方法实现多线程,而调用run方法没有实现多线程
        //Start:
        //  用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。
        //  通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到spu时间片,
        //  就开始执行run()方法,这里方法run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止。
        //Run:
        //  run()方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,
        //  其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,
        //  这样就没有达到写线程的目的。
        //总结:调用start方法方可启动线程,而run方法只是thread的一个普通方法调用,还是在主线程里执行。
        t1.start();
        t2.start();

        t1.run();
        t2.run();
    }
    /**
start方法实现了多线程,程序测试的就是多线程的影响
调用结果是:
当前调用synchronThread1方法的线程是:thread1
这是syschronThread1方法执行的同步方法,0
这是syschronThread1方法执行的同步方法,1
这是syschronThread1方法执行的同步方法,2
这是syschronThread1方法执行的同步方法,3
这是syschronThread1方法执行的同步方法,4
当前调用synchronThread1方法的线程是:thread2
这是syschronThread1方法执行的同步方法,0
这是syschronThread1方法执行的同步方法,1
这是syschronThread1方法执行的同步方法,2
这是syschronThread1方法执行的同步方法,3
这是syschronThread1方法执行的同步方法,4


run方法只是一个线程,按顺序执行罢了,没有测试的必要
当前调用synchronThread1方法的线程是:main
这是syschronThread1方法执行的同步方法,0
这是syschronThread1方法执行的同步方法,1
这是syschronThread1方法执行的同步方法,2
这是syschronThread1方法执行的同步方法,3
这是syschronThread1方法执行的同步方法,4
当前调用synchronThread1方法的线程是:main
这是syschronThread1方法执行的同步方法,0
这是syschronThread1方法执行的同步方法,1
这是syschronThread1方法执行的同步方法,2
这是syschronThread1方法执行的同步方法,3
这是syschronThread1方法执行的同步方法,4
     */
}

1.2 同步块

public class TestThread {

    //synchronized的同步锁是this对象(类的对象)

    //2、修饰代码块
    public void syschronThread2(){
        synchronized(this){
            System.out.println("当前调用synchronThread2方法的线程是:"+Thread.currentThread().getName());
            for(int i=0;i<5;i++){
                System.out.println("这是syschronThread2方法执行的同步块,"+i);
            }
        }
    }

    public static void main(String[] args) {
        final TestThread testThread=new TestThread();
        //测试1 syschronThread1
        Thread t1=new Thread(new Runnable() {

            public void run() {
                // TODO Auto-generated method stub
                testThread.syschronThread2();
            }
        },"thread3");
        Thread t2=new Thread(new Runnable(){

            public void run() {
                // TODO Auto-generated method stub
                testThread.syschronThread2();
            }

        },"thread4");
        t1.start();
        t2.start();
    }
    /**
运行结果是:
当前调用synchronThread2方法的线程是:thread3
这是syschronThread2方法执行的同步块,0
这是syschronThread2方法执行的同步块,1
这是syschronThread2方法执行的同步块,2
这是syschronThread2方法执行的同步块,3
这是syschronThread2方法执行的同步块,4
当前调用synchronThread2方法的线程是:thread4
这是syschronThread2方法执行的同步块,0
这是syschronThread2方法执行的同步块,1
这是syschronThread2方法执行的同步块,2
这是syschronThread2方法执行的同步块,3
这是syschronThread2方法执行的同步块,4

     */
}

1.3两者综合使用

public class TestThread {

    //synchronized的同步锁是this对象(类的对象)

    //1、修饰类
    public synchronized void syschronThread1(){
        System.out.println("当前调用synchronThread1方法的线程是:"+Thread.currentThread().getName());
        for(int i=0;i<5;i++){
            System.out.println("这是syschronThread1方法执行的同步方法,"+i);
        }
    }
    //2、修饰代码块
    public void syschronThread2(){
        synchronized(this){
            System.out.println("当前调用synchronThread2方法的线程是:"+Thread.currentThread().getName());
            for(int i=0;i<5;i++){
                System.out.println("这是syschronThread2方法执行的同步方法,"+i);
            }
        }

    }

    public static void main(String[] args) {
        final TestThread testThread=new TestThread();
        Thread t2=new Thread(new Runnable(){

            public void run() {
                // TODO Auto-generated method stub
                testThread.syschronThread2();
            }

        },"thread2");
        Thread t1=new Thread(new Runnable() {

            public void run() {
                // TODO Auto-generated method stub
                testThread.syschronThread1();
            }
        },"thread1");
        t1.start();
        t2.start();
    }

    /**
调用结果是:
当前调用synchronThread1方法的线程是:thread1
这是syschronThread1方法执行的同步方法,0
这是syschronThread1方法执行的同步方法,1
这是syschronThread1方法执行的同步方法,2
这是syschronThread1方法执行的同步方法,3
这是syschronThread1方法执行的同步方法,4
当前调用synchronThread2方法的线程是:thread2
这是syschronThread2方法执行的同步方法,0
这是syschronThread2方法执行的同步方法,1
这是syschronThread2方法执行的同步方法,2
这是syschronThread2方法执行的同步方法,3
这是syschronThread2方法执行的同步方法,4
     */
}

得出结论是:
syschronTread1和syschronTread2都是使用的是this锁,所以当一个线程占用锁的时候,另外一个线程需要等待

2、synchronized的同步锁是类对象
public class TestThread {

    //synchronized的同步锁是类对象)

    //1、修饰类
    public static synchronized void syschronThread1(){
        System.out.println("当前调用synchronThread1方法的线程是:"+Thread.currentThread().getName());
        for(int i=0;i<5;i++){
            System.out.println("这是syschronThread1方法执行的同步方法,"+i);
             try   
             {    
                  Thread.sleep(500);    
             }   
             catch (InterruptedException ie)   
             {    
             }    
        }
    }
    //2、修饰代码块
    public void syschronThread2(){
        synchronized(TestThread.class){
            System.out.println("当前调用synchronThread2方法的线程是:"+Thread.currentThread().getName());
            for(int i=0;i<5;i++){
                System.out.println("这是syschronThread2方法执行的同步方法,"+i);
                 try   
                 {    
                      Thread.sleep(500);    
                 }   
                 catch (InterruptedException ie)   
                 {    
                 }    
            }
        }

    }

    public static void main(String[] args) {
        Thread thread2=new Thread(new Runnable(){

            public void run() {
                // TODO Auto-generated method stub
                new TestThread().syschronThread2();

            }
        },"thread2");
        Thread thread1=new Thread(new Runnable(){

            public void run() {
                // TODO Auto-generated method stub
                TestThread.syschronThread1();
            }

        },"thread1");
        thread2.start();
        thread1.start();
    }

    /**
     * 运行结果是:
当前调用synchronThread1方法的线程是:thread1
这是syschronThread1方法执行的同步方法,0
这是syschronThread1方法执行的同步方法,1
这是syschronThread1方法执行的同步方法,2
这是syschronThread1方法执行的同步方法,3
这是syschronThread1方法执行的同步方法,4
当前调用synchronThread2方法的线程是:thread2
这是syschronThread2方法执行的同步方法,0
这是syschronThread2方法执行的同步方法,1
这是syschronThread2方法执行的同步方法,2
这是syschronThread2方法执行的同步方法,3
这是syschronThread2方法执行的同步方法,4
     */
}

小知识点:
sleep和wait的区别:
sleep(100L)是占用cpu,线程休眠100毫秒,其他进程不能再占用cpu资源,
wait(100L)是进入等待池中等待,交出cpu 等系统资源供其他进程使用,在这100毫秒中,该线程可以被其他线程notify,但不同的是其他在等待池中的线程不被notify不会出来,但这个线程 在等待100毫秒后会自动进入就绪队列等待系统分配资源,
换句话说,sleep(100)在100毫秒后肯定会运行,但wait在100毫秒后还有等待 os调用分配资源,所以wait100的停止运行时间是不确定的,但至少是100毫秒。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值