1.静态同步synchronized方法与synchronized(class)代码块
关键字synchronized还可以应用在static静态方法上,如果这样写,那是对当前的*java文件对应的Class类进行持锁,测试代码如下:
package test;
/**
* @Author LiBinquan
*/
public class Service {
synchronized public static void printA(){
try{
System.out.println("线程名称为:"+Thread.currentThread().getName()+" 在 "+System.currentTimeMillis()+" 进入线程printA");
Thread.sleep(3000);
System.out.println("线程名称为:"+Thread.currentThread().getName()+" 在 "+System.currentTimeMillis()+" 离开线程printA");
}catch (InterruptedException e){
e.printStackTrace();
}
}
synchronized public static void printB(){
System.out.println("线程名称为:"+Thread.currentThread().getName()+" 在 "+System.currentTimeMillis()+" 进入线程printB");
System.out.println("线程名称为:"+Thread.currentThread().getName()+" 在 "+System.currentTimeMillis()+" 离开线程printB");
}
}
线程1:
package test;
/**
* @Author LiBinquan
*/
public class ThreadTest1 extends Thread{
@Override
public void run() {
Service.printA();
}
}
线程2:
package test;
/**
* @Author LiBinquan
*/
public class ThreadTest2 extends Thread{
@Override
public void run() {
Service.printB();
}
}
运行类:
package test;
/**
* @Author LiBinquan
*/
public class Run {
public static void main(String[] args) throws InterruptedException {
ThreadTest1 threadTest1 = new ThreadTest1();
threadTest1.setName("A");
threadTest1.start();
ThreadTest2 threadTest2 = new ThreadTest2();
threadTest2.setName("B");
threadTest2.start();
}
}
输出:
从运行结果来看,并没有特别之处,都是同步的效果,和将synchronized关键字加到非static方法上使用的效果是一样的。其实还是有本质上的不同的,synchronized关键字加到static静态方法上是给CLass类上锁,而synchronized关键字加到非static静态方法上是给对象上锁。
接下来我们加上一段 synchronized 关键字加到非static方法代码,代码如下:
package test;
/**
* @Author LiBinquan
*/
public class Service {
synchronized public static void printA(){
try{
System.out.println("线程名称为:"+Thread.currentThread().getName()+" 在 "+System.currentTimeMillis()+" 进入线程printA");
Thread.sleep(3000);
System.out.println("线程名称为:"+Thread.currentThread().getName()+" 在 "+System.currentTimeMillis()+" 离开线程printA");
}catch (InterruptedException e){
e.printStackTrace();
}
}
synchronized public static void printB(){
System.out.println("线程名称为:"+Thread.currentThread().getName()+" 在 "+System.currentTimeMillis()+" 进入线程printB");
System.out.println("线程名称为:"+Thread.currentThread().getName()+" 在 "+System.currentTimeMillis()+" 离开线程printB");
}
synchronized public void printC(){
System.out.println("线程名称为:"+Thread.currentThread().getName()+" 在 "+System.currentTimeMillis()+" 进入线程printC");
System.out.println("线程名称为:"+Thread.currentThread().getName()+" 在 "+System.currentTimeMillis()+" 离开线程printC");
}
}
增加线程3:
package test;
/**
* @Author LiBinquan
* @since dw 3.0.0
*/
public class ThreadTest3 extends Thread{
private Service service;
public ThreadTest3(Service service){
super();
this.service = service;
}
@Override
public void run() {
service.printC();
}
}
运行类:
package test;
/**
* @Author LiBinquan
*/
public class Run {
public static void main(String[] args) throws InterruptedException {
Service service = new Service();
ThreadTest1 threadTest1 = new ThreadTest1();
threadTest1.setName("A");
threadTest1.start();
ThreadTest2 threadTest2 = new ThreadTest2();
threadTest2.setName("B");
threadTest2.start();
ThreadTest3 threadTest3 = new ThreadTest3(service);
threadTest3.setName("C");
threadTest3.start();
}
}
输出:
这边输出是异步的原因是持有不同的锁,一个是对象锁,一个是Class锁,而Class锁可以对类的所有对象实例起作用。用一个测试用例来说明,代码如下:
package test;
/**
* @Author LiBinquan
*/
public class Service {
synchronized public static void printA(){
try{
System.out.println("线程名称为:"+Thread.currentThread().getName()+" 在 "+System.currentTimeMillis()+" 进入线程printA");
Thread.sleep(3000);
System.out.println("线程名称为:"+Thread.currentThread().getName()+" 在 "+System.currentTimeMillis()+" 离开线程printA");
}catch (InterruptedException e){
e.printStackTrace();
}
}
synchronized public static void printB(){
System.out.println("线程名称为:"+Thread.currentThread().getName()+" 在 "+System.currentTimeMillis()+" 进入线程printB");
System.out.println("线程名称为:"+Thread.currentThread().getName()+" 在 "+System.currentTimeMillis()+" 离开线程printB");
}
}
线程1:
package test;
/**
* @Author LiBinquan
*/
public class ThreadTest1 extends Thread{
private Service service;
public ThreadTest1(Service service){
super();
this.service = service;
}
@Override
public void run() {
service.printA();
}
}
线程2:
package test;
/**
* @Author LiBinquan
*/
public class ThreadTest2 extends Thread{
private Service service;
public ThreadTest2(Service service){
super();
this.service = service;
}
@Override
public void run() {
service.printB();
}
}
运行类:
package test;
/**
* @Author LiBinquan
*/
public class Run {
public static void main(String[] args) throws InterruptedException {
Service service = new Service();
ThreadTest1 threadTest1 = new ThreadTest1(service);
threadTest1.setName("A");
threadTest1.start();
ThreadTest2 threadTest2 = new ThreadTest2(service);
threadTest2.setName("B");
threadTest2.start();
}
}
输出:
同步synchronized(class)代码块的作用其实和synchronized static 方法的作用一样。
修改代码如下:
package test;
/**
* @Author LiBinquan
*/
public class Service {
public static void printA(){
synchronized(Service.class) {
try {
System.out.println("线程名称为:" + Thread.currentThread().getName() + " 在 " + System.currentTimeMillis() + " 进入线程printA");
Thread.sleep(3000);
System.out.println("线程名称为:" + Thread.currentThread().getName() + " 在 " + System.currentTimeMillis() + " 离开线程printA");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void printB(){
synchronized(Service.class) {
System.out.println("线程名称为:" + Thread.currentThread().getName() + " 在 " + System.currentTimeMillis() + " 进入线程printB");
System.out.println("线程名称为:" + Thread.currentThread().getName() + " 在 " + System.currentTimeMillis() + " 离开线程printB");
}
}
}
输出: