(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)只能在实例方法中进行调用,这个时候如果是同一个实例,则会互相牵制,如果是不同实例,将互不影响。