zoukankan      html  css  js  c++  java
  • 59、synchronized同步代码块

    synchronized同步方法的问题

    有些情况下,在方法上面加synchronized同步,会有性能问题。
    请看下面代码,来计算下两个线程执行的耗时:

    package com.sutaoyu.Thread;
    
    public class SynchronizedTest02 {
        public static long begin1;
        public static long end1;
        public static long begin2;
        public static long end2;
        
        public static void main(String[] args) {
            final LongTask longTask = new LongTask();
            
            Thread t1 = new Thread() {
                public void run() {
                    begin1 = System.currentTimeMillis();
                    //执行耗时较长的任务方法
                    longTask.changeNum(true);
                    end1 = System.currentTimeMillis();
                }
            };
            
            Thread t2 = new Thread() {
                public void run() {
                    begin2 = System.currentTimeMillis();
                    //执行耗时较长的任务方法
                    longTask.changeNum(false);
                    end2 = System.currentTimeMillis();
                }
            };
            
            t1.start();
            t2.start();
            
            //先让主线程睡眠,保证t1和t2线程执行完毕之后再计算时间
            try {
                Thread.sleep(10000);
            }catch(InterruptedException e) {
                e.printStackTrace();
            }
            
            long begin = 0;
            long end = 0;
            
            //将先执行的线程的时间和最后执行线程的时间获取到
            if(begin1 > begin2) {
                begin = begin2;
            }else {
                begin = begin1;
            }
            
            if(end1 > end2) {
                end = end1;
            }else {
                begin = begin1;
            }
            
            if(end1 > end2) {
                end = end1;
            }else {
                end = end2;
            }
            
            System.out.println("两个线程总共耗时:" + (end -begin)/1000 + "秒");
            
        }
    }

    使用同步代码块完善上面代码

    上面代码打印结果是6秒,里面使用Thread.sleep方法来模拟了一个执行耗时较长的代码,假设这段代码并不会涉及到安全问题,所以就没有比较加入同步了。
    来使用synchronized代码块来修改下上面的LongTask类。

    package com.sutaoyu.Thread;
    
    public class SynchronizedTest02 {
        public static long begin1;
        public static long end1;
        public static long begin2;
        public static long end2;
        
        public static void main(String[] args) {
            final LongTask longTask = new LongTask();
            
            Thread t1 = new Thread() {
                public void run() {
                    begin1 = System.currentTimeMillis();
                    //执行耗时较长的任务方法
                    longTask.changeNum(true);
                    end1 = System.currentTimeMillis();
                }
            };
            
            Thread t2 = new Thread() {
                public void run() {
                    begin2 = System.currentTimeMillis();
                    //执行耗时较长的任务方法
                    longTask.changeNum(false);
                    end2 = System.currentTimeMillis();
                }
            };
            
            t1.start();
            t2.start();
            
            //先让主线程睡眠,保证t1和t2线程执行完毕之后再计算时间
            try {
                Thread.sleep(10000);
            }catch(InterruptedException e) {
                e.printStackTrace();
            }
            
            long begin = 0;
            long end = 0;
            
            //将先执行的线程的时间和最后执行线程的时间获取到
            if(begin1 > begin2) {
                begin = begin2;
            }else {
                begin = begin1;
            }
            
            if(end1 > end2) {
                end = end1;
            }else {
                begin = begin1;
            }
            
            if(end1 > end2) {
                end = end1;
            }else {
                end = end2;
            }
            
            System.out.println("两个线程总共耗时:" + (end -begin)/1000 + "秒");
            
        }
    }

    修改后将需要同步的代码放到synchronized代码块中,再次运行SynchronizedTest02类,打印结果是3秒,因为那段耗时较长的代码是在异步情况下运行,所以节省了一些时间。

    注意:多个线程在执行synchronized同步代码块时,代码块括号里面可以传入任意对象,但一定要保证多个线程访问的是同一个对象。

    比如将LongTask中的成员变量Object obj = new Object();移动到changeNum方法中,在t1和t2两个线程中分别调用了changeNum方法,这样会各自创建一个Object对象,仍然会导致线程安全问题发生。

  • 相关阅读:
    一些经验
    倍增(在线)求LCA
    IDA*算法——骑士精神
    A*算法——第K短路
    (持续更新)一些黑科技和技巧
    逆元
    方便人类——信息学训练专用库
    PHP单点登陆
    PHP 中运用 elasticsearch
    PHP斐波那契数列
  • 原文地址:https://www.cnblogs.com/zhuifeng-mayi/p/10156496.html
Copyright © 2011-2022 走看看