java-测试synchronized使用xxx.class和this使用的区别

synchronized测试1

写两个线程调用同一个方法,在其中分别做一个class和this的调用,看结果

1.xx.class

public class Test{
    public static void main(String[] args) {
        System.out.println(new Date().toLocaleString()+";开始创建t1...");
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                new Test().test("t1");
            }
        });
        System.out.println(new Date().toLocaleString()+";开始执行t1...");
        t1.start();
        System.out.println(new Date().toLocaleString()+";开始创建t2...");
        Thread t2 = new Thread(new Runnable() {
            public void run() {
                new Test().test("t2");
            }
        });
        System.out.println(new Date().toLocaleString()+";开始执行t2...");
        t2.start();
    }

    public  void test(String n){
        System.out.println(new Date().toLocaleString()+";"+n+"来了");
        synchronized (Test.class) {
            System.out.println(new Date().toLocaleString()+";"+n+"   我在这里休眠5秒");
            try {
                Thread.sleep(5*1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(new Date().toLocaleString()+";"+n+"   结束");
    }
}

打印 

2015-10-19 13:56:46;开始创建t1...
2015-10-19 13:56:47;开始执行t1...
2015-10-19 13:56:47;开始创建t2...
2015-10-19 13:56:47;t1来了
2015-10-19 13:56:47;t1   我在这里休眠5秒
2015-10-19 13:56:47;开始执行t2...
2015-10-19 13:56:47;t2来了
2015-10-19 13:56:52;t2   我在这里休眠5秒
2015-10-19 13:56:52;t1   结束
2015-10-19 13:56:57;t2   结束

从打印的结果可以看出,使用class在执行到synchronized时会等待其他占用的线程执行玩才会继续执行

2.对比this

//将上面的案例中的synchronized (Test.class) { 修改成
synchronized (this) {

执行打印输出结果

2015-10-19 14:01:22;开始创建t1...
2015-10-19 14:01:22;开始执行t1...
2015-10-19 14:01:22;开始创建t2...
2015-10-19 14:01:22;t1来了
2015-10-19 14:01:22;开始执行t2...
2015-10-19 14:01:22;t1   我在这里休眠5秒
2015-10-19 14:01:22;t2来了
2015-10-19 14:01:22;t2   我在这里休眠5秒
2015-10-19 14:01:27;t1   结束
2015-10-19 14:01:27;t2   结束

可以看到,使用this执行线程时只会考虑到同一个线程中的同步问题,严格来说是无法达到真正意义上的线程同步

通过调用不同的方法再次测试

首先看使用class代码展示

    public class Test{
        public static void main(String[] args) {
            System.out.println(new Date().toLocaleString()+";开始创建t1...");
            Thread t1 = new Thread(new Runnable() {
                public void run() {
                    new Test().test("t1");
                }
            });
            System.out.println(new Date().toLocaleString()+";开始执行t1...");
            t1.start();
            System.out.println(new Date().toLocaleString()+";开始创建t2...");
            Thread t2 = new Thread(new Runnable() {
                public void run() {
                    new Test().test1("t2");
                }
            });
            System.out.println(new Date().toLocaleString()+";开始执行t2...");
            t2.start();
        }
    
        public  void test(String n){
            System.out.println(new Date().toLocaleString()+";"+n+"来了");
            synchronized (Test.class) {
                System.out.println(new Date().toLocaleString()+";"+n+"   我在这里休眠5秒");
                try {
                    Thread.sleep(5*1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(new Date().toLocaleString()+";"+n+"   结束");
        }
        

        
        public  void test1(String n){
            System.out.println(new Date().toLocaleString()+";"+n+"来了");
            synchronized (Test.class) {
                System.out.println(new Date().toLocaleString()+";"+n+"   我在这里休眠5秒");
                try {
                    Thread.sleep(5*1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(new Date().toLocaleString()+";"+n+"   结束");
        }
    }

执行打印结果

2015-10-19 14:04:58;开始创建t1...
2015-10-19 14:04:58;开始执行t1...
2015-10-19 14:04:58;开始创建t2...
2015-10-19 14:04:58;t1来了
2015-10-19 14:04:58;t1   我在这里休眠5秒
2015-10-19 14:04:58;开始执行t2...
2015-10-19 14:04:58;t2来了
2015-10-19 14:05:03;t2   我在这里休眠5秒
2015-10-19 14:05:03;t1   结束
2015-10-19 14:05:08;t2   结束

通过打印结果可以看到基本与同一个方法执行的结果相同

同样也做this的测试

//将上面的案例中的synchronized (Test.class) { 修改成
synchronized (this) {

打印结果

2015-10-19 14:08:22;开始创建t1...
2015-10-19 14:08:22;开始执行t1...
2015-10-19 14:08:22;开始创建t2...
2015-10-19 14:08:22;t1来了
2015-10-19 14:08:22;t1   我在这里休眠5秒
2015-10-19 14:08:22;开始执行t2...
2015-10-19 14:08:22;t2来了
2015-10-19 14:08:22;t2   我在这里休眠5秒
2015-10-19 14:08:27;t1   结束
2015-10-19 14:08:27;t2   结束

打印结果基本相同

所以得出:在使用线程同步时,处理特殊情况外基本应该使用class

测试static中的线程同步

    
    public class Test{
        public static void main(String[] args) {
            System.out.println(new Date().toLocaleString()+";开始创建t1...");
            Thread t1 = new Thread(new Runnable() {
                public void run() {
                    test("t1");
                }
            });
            System.out.println(new Date().toLocaleString()+";开始执行t1...");
            t1.start();
            System.out.println(new Date().toLocaleString()+";开始创建t2...");
            Thread t2 = new Thread(new Runnable() {
                public void run() {
                    test("t2");
                }
            });
            System.out.println(new Date().toLocaleString()+";开始执行t2...");
            t2.start();
        }
    
        public static void test(String n){
            System.out.println(new Date().toLocaleString()+";"+n+"来了");
            synchronized (Test.class) {
                System.out.println(new Date().toLocaleString()+";"+n+"   我在这里休眠5秒");
                try {
                    Thread.sleep(5*1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(new Date().toLocaleString()+";"+n+"   结束");
        }
        

        
    }

打印

2015-10-19 14:10:22;开始创建t1...
2015-10-19 14:10:23;开始执行t1...
2015-10-19 14:10:23;开始创建t2...
2015-10-19 14:10:23;t1来了
2015-10-19 14:10:23;t1   我在这里休眠5秒
2015-10-19 14:10:23;开始执行t2...
2015-10-19 14:10:23;t2来了
2015-10-19 14:10:28;t2   我在这里休眠5秒
2015-10-19 14:10:28;t1   结束
2015-10-19 14:10:33;t2   结束

从结果中可以看出与class执行是一样的,不区分static。

原文地址:https://www.cnblogs.com/hwaggLee/p/4891800.html