• synchronized(this)区别于synchronized(myclass-class)


    (1)synchronized(myclass-class)用于静态方法中

    static void myMethod() {
      synchronized(MyClass.class) {
        //code
      }
    }

    注:静态方法中只能用synchronized(MyClass.class),不能用synchronized(this)。idea中用synchronized(this)会报错。

    等同于:

    static synchronized void myMethod() {
      //code
    }

    synchronized(MyClass.class) 测试例子, 由于是静态方法, 可以被类调用,也可以被实例调用:

    四个线程,两个通过实例调用,两个通过类调用

    public class MyClass {
    
        public static void myMethod() {
            try {
                synchronized (MyClass.class) {
                    String name = Thread.currentThread().getName();
                    System.out.println(name + "线程正在开始任务。");
                    for (int i = 0; i < 5; i++) {
                        Thread.sleep(1000);
                        System.out.println(name + "正在执行任务。");
                    }
                    System.out.println(name + "线程任务执行完毕。");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            Thread thread1 = new Thread1();
            thread1.setName("thread1");
            Thread thread2 = new Thread2();
            thread2.setName("thread2");
            Thread thread3 = new Thread3();
            thread3.setName("thread3");
            Thread thread4 = new Thread4();
            thread4.setName("thread4");
            thread1.start();
            thread2.start();
            thread3.start();
            thread4.start();
        }
    }
    
    class Thread1 extends Thread {
        @Override
        public void run() {
            MyClass.myMethod();
        }
    }
    
    class Thread2 extends Thread {
        @Override
        public void run() {
            MyClass.myMethod();
        }
    }
    
    class Thread3 extends Thread {
        @Override
        public void run() {
            MyClass myClass = new MyClass();
            myClass.myMethod();
        }
    }
    
    class Thread4 extends Thread {
        @Override
        public void run() {
            MyClass myClass = new MyClass();
            myClass.myMethod();
        }
    }

    输出结果:

    thread2线程正在开始任务。
    thread2正在执行任务。
    thread2正在执行任务。
    thread2正在执行任务。
    thread2正在执行任务。
    thread2正在执行任务。
    thread2线程任务执行完毕。
    thread4线程正在开始任务。
    thread4正在执行任务。
    thread4正在执行任务。
    thread4正在执行任务。
    thread4正在执行任务。
    thread4正在执行任务。
    thread4线程任务执行完毕。
    thread3线程正在开始任务。
    thread3正在执行任务。
    thread3正在执行任务。
    thread3正在执行任务。
    thread3正在执行任务。
    thread3正在执行任务。
    thread3线程任务执行完毕。
    thread1线程正在开始任务。
    thread1正在执行任务。
    thread1正在执行任务。
    thread1正在执行任务。
    thread1正在执行任务。
    thread1正在执行任务。
    thread1线程任务执行完毕。

    可以看出, 在静态方法中

    synchronized(MyClass.class) {

        //code

    }

    只能由一个线程访问。

    (2)synchronized(myclass-class)用于实例方法中

    这个是时候只能通过创建一个实例调用。

    demo测试代码:

    public class MyClass {
    
        public void myMethod() {
            try {
                synchronized (MyClass.class) {
                    String name = Thread.currentThread().getName();
                    System.out.println(name + "线程正在开始任务。");
                    for (int i = 0; i < 5; i++) {
                        Thread.sleep(1000);
                        System.out.println(name + "正在执行任务。");
                    }
                    System.out.println(name + "线程任务执行完毕。");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            final MyClass myClass = new MyClass();
            Thread thread1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    myClass.myMethod();
                }
            });
            thread1.setName("thread1");
            Thread thread2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    myClass.myMethod();
                }
            });
            thread2.setName("thread2");
            Thread3 thread3 = new Thread3();
            thread3.setName("thread3");
            thread1.start();
            thread2.start();
            thread3.start();
        }
    }
    
    class Thread3 extends Thread {
        @Override
        public void run() {
            MyClass myClass = new MyClass();
            myClass.myMethod();
        }
    }
    thread1线程正在开始任务。
    thread1正在执行任务。
    thread1正在执行任务。
    thread1正在执行任务。
    thread1正在执行任务。
    thread1正在执行任务。
    thread1线程任务执行完毕。
    thread3线程正在开始任务。
    thread3正在执行任务。
    thread3正在执行任务。
    thread3正在执行任务。
    thread3正在执行任务。
    thread3正在执行任务。
    thread3线程任务执行完毕。
    thread2线程正在开始任务。
    thread2正在执行任务。
    thread2正在执行任务。
    thread2正在执行任务。
    thread2正在执行任务。
    thread2正在执行任务。
    thread2线程任务执行完毕。

    这边有三个实例,两个thread1和thread2共用一个,thread3自己开辟一个实例。发现只会有一个线程访问。其他的必须等待。情况跟(1)一样。

    (3)synchronized(this)位于实例方法中。(静态方法不能用这个)

    测试demo:就是将(2)中的synchronized(MyClass.class)改成synchronized(this)

    public class MyClass {
    
        public void myMethod() {
            try {
                synchronized (this) {
                    String name = Thread.currentThread().getName();
                    System.out.println(name + "线程正在开始任务。");
                    for (int i = 0; i < 5; i++) {
                        Thread.sleep(1000);
                        System.out.println(name + "正在执行任务。");
                    }
                    System.out.println(name + "线程任务执行完毕。");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            final MyClass myClass = new MyClass();
            Thread thread1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    myClass.myMethod();
                }
            });
            thread1.setName("thread1");
            Thread thread2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    myClass.myMethod();
                }
            });
            thread2.setName("thread2");
            Thread3 thread3 = new Thread3();
            thread3.setName("thread3");
            thread1.start();
            thread2.start();
            thread3.start();
        }
    }
    
    class Thread3 extends Thread {
        @Override
        public void run() {
            MyClass myClass = new MyClass();
            myClass.myMethod();
        }
    }

    输出1:

    thread2线程正在开始任务。
    thread3线程正在开始任务。
    thread2正在执行任务。
    thread3正在执行任务。
    thread3正在执行任务。
    thread2正在执行任务。
    thread3正在执行任务。
    thread2正在执行任务。
    thread2正在执行任务。
    thread3正在执行任务。
    thread3正在执行任务。
    thread3线程任务执行完毕。
    thread2正在执行任务。
    thread2线程任务执行完毕。
    thread1线程正在开始任务。
    thread1正在执行任务。
    thread1正在执行任务。
    thread1正在执行任务。
    thread1正在执行任务。
    thread1正在执行任务。
    thread1线程任务执行完毕。

    输出2

    thread3线程正在开始任务。
    thread1线程正在开始任务。
    thread1正在执行任务。
    thread3正在执行任务。
    thread1正在执行任务。
    thread3正在执行任务。
    thread1正在执行任务。
    thread3正在执行任务。
    thread3正在执行任务。
    thread1正在执行任务。
    thread3正在执行任务。
    thread3线程任务执行完毕。
    thread1正在执行任务。
    thread1线程任务执行完毕。
    thread2线程正在开始任务。
    thread2正在执行任务。
    thread2正在执行任务。
    thread2正在执行任务。
    thread2正在执行任务。
    thread2正在执行任务。
    thread2线程任务执行完毕。

    可以看出thread1和thread2是牵制的, 一前一后。thread3不受影响。

    总结:

    1. synchronized(myclass-class)可用于静态方法或者实例方法中,可以通过类名或者实例进行调用,但是都会只有一个线程执行,其他等待。

    2. synchronized(this)只能在实例方法中进行调用,这个时候如果是同一个实例,则会互相牵制,如果是不同实例,将互不影响。

  • 相关阅读:
    百度编辑器如何能实现直接粘贴把图片上传到服务器中
    百度ueditor如何能实现直接粘贴把图片上传到服务器中
    ueditor如何能实现直接粘贴把图片上传到服务器中
    html+SpringMVC超大视频上传解决方案
    html+java超大视频上传解决方案
    html+JSP超大视频上传解决方案
    html+CSharp超大视频上传解决方案
    html+.net超大视频上传解决方案
    SAP 函数CRM_ORDERADM_I_PROD_DETERM_OW的单元测试方法
    SAP CRM Opportunity行项目Alternative ID的填充逻辑
  • 原文地址:https://www.cnblogs.com/chenmz1995/p/12111467.html
Copyright © 2020-2023  润新知