多线程之synchronized同步语句块(4)

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");
         }
    }
}

输出:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值