• 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。

  • 相关阅读:
    线程池
    自定义死锁
    不安全线程取钱
    JUC Lock实现类ReentrantLock使用说明
    同步方法跟同步方法块 synchronized
    线程的管程法跟信号灯法_生产者消费模式
    CopyOnWriteArrayList JUC当中安全容器
    inserttextatcursorinacontenteditablediv
    Android开发——NDK开发入门
    Linux下线程同步对象(1)——互斥量
  • 原文地址:https://www.cnblogs.com/hwaggLee/p/4891800.html
Copyright © 2020-2023  润新知