• Java多线程--synchronized(二)


    synchronized 同步语句块

    synchronized方法的缺点

    直接在方法上加synchronized关键字在某些情况下存在弊端,比如线程A调用同步方法执行长时间任务,那么其他线程将会等待很长时间。

    package ch02.test3;
    /*
        synchronized 同步代码块
     */
    public class Task {
        private String getData1;
        private String getData2;
        public synchronized void doLongTimeTask() {
            try{
                System.out.println("begin task");
                Thread.sleep(3000);
                String tmpGetData1 = "长时间执行任务返回结果1 threadname=" + Thread.currentThread().getName();
                String tmpGetData2 = "长时间执行任务返回结果2 threadname=" + Thread.currentThread().getName();
                getData1 = tmpGetData1;
                getData2 = tmpGetData2;
                System.out.println(getData1);
                System.out.println(getData2);
                System.out.println("end task");
            }catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    class CommonUtils {
        public static long beginTime1;
        public static long endTime1;
        public static long beginTime2;
        public static long endTime2;
    }
    
    class MyThread1 extends Thread {
        private Task task;
    
        public MyThread1(Task task) {
            this.task = task;
        }
    
        @Override
        public void run() {
            super.run();
            CommonUtils.beginTime1 = System.currentTimeMillis();
            this.task.doLongTimeTask();
            CommonUtils.endTime1 = System.currentTimeMillis();
        }
    }
    
    class MyThread2 extends Thread {
        private Task task;
    
        public MyThread2(Task task) {
            this.task = task;
        }
    
        @Override
        public void run() {
            super.run();
            CommonUtils.beginTime2 = System.currentTimeMillis();
            this.task.doLongTimeTask();
            CommonUtils.endTime2 = System.currentTimeMillis();
        }
    }
    
    class Run {
        public static void main(String[] args) {
            Task task = new Task();
            MyThread1 myThread1 = new MyThread1(task);
            myThread1.start();
            MyThread2 myThread2 = new MyThread2(task);
            myThread2.start();
    
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            long beginTime = Math.min(CommonUtils.beginTime1, CommonUtils.beginTime2);
            long endTime = Math.max(CommonUtils.endTime1, CommonUtils.endTime2);
            System.out.println("总耗时:"+ (endTime - beginTime) / 1000 + "s");
        }
    }
    

    output:

    begin task
    长时间执行任务返回结果1 threadname=Thread-0
    长时间执行任务返回结果2 threadname=Thread-0
    end task
    begin task
    长时间执行任务返回结果1 threadname=Thread-1
    长时间执行任务返回结果2 threadname=Thread-1
    end task
    总耗时:6s
    

    synchronized同步代码块的使用

    修改doLongTimeTask()方法,去掉方法上的synchronized,在其中添加同步代码块:

    public void doLongTimeTask() {
            try{
                System.out.println("begin task");
                Thread.sleep(3000);
                String tmpGetData1 = "长时间执行任务返回结果1 threadname=" + Thread.currentThread().getName();
                String tmpGetData2 = "长时间执行任务返回结果2 threadname=" + Thread.currentThread().getName();
                synchronized (this) {
                    getData1 = tmpGetData1;
                    getData2 = tmpGetData2;
                }
                System.out.println(getData1);
                System.out.println(getData2);
                System.out.println("end task");
            }catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    

    output:

    begin task
    begin task
    长时间执行任务返回结果1 threadname=Thread-1
    长时间执行任务返回结果2 threadname=Thread-0
    end task
    长时间执行任务返回结果1 threadname=Thread-0
    长时间执行任务返回结果2 threadname=Thread-0
    end task
    总耗时:3s
    

    当一个线程访问同步代码块时,其他线程仍然可以访问该对象的非同步代码块
    方法中线程在synchronized (this) 同步代码块是同步的,不在同步代码块的部分是异步的

    • 和synchronized方法相似,当一个线程访问anyObject对象的synchronized(this)同步代码块时,其他线程中所有同步代码块的访问将被阻塞,说明synchronized使用的“对象监视器”是一个。

    小结

    1. synchronized同步方法
      1.1 同一时间只能有一个线程执行synchronized同步方法。
      1.2 对同一对象的所有其他synchronized同步方法和synchronized(this)同步代码块调用呈阻塞状态。
    2. synchronized(this)同步代码块同步代码块
      1.1 同一时间只能有一个线程执行synchronized(this)同步代码块。
      1.2 对同一对象的所有其他synchronized同步方法和synchronized(this)同步代码块调用呈阻塞状态。

    作者:lykxbg —— 来一块小饼干

    出处:http://www.cnblogs.com/lykxbg/

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    简易花台制作攻略
    欢迎
    VxWorks操作系统MakeFile(三)
    原创连载:往事
    VxWorks操作系统MakeFile(五)
    致亲爱的板儿的一封信
    VxWorks操作系统MakeFile(二)
    华为NE5000E集群路由器荣获InfoVision奖
    台式机安装黑苹果Mac OS X Snow Leopard 10.6相关资源
    未能加载文件或程序集Office, Version=2.2.0.0, Culture=neutral, PublicKeyToken=null或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。 (异常来自 HRESULT:0x80131040)
  • 原文地址:https://www.cnblogs.com/lykxbg/p/13650380.html
Copyright © 2020-2023  润新知