• 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/

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

  • 相关阅读:
    js 去掉文本域中的空格
    网站开发步骤
    获取客户端、服务器、本地IP地址
    c#用反射原理递归遍历复杂实体对象
    jquery1.8在ie8下not无效?
    状态模式
    虚函数和抽象函数的区别
    HashTable、HashSet和Dictionary的区别
    sql视图学习笔记--视图
    html背景为灰色 不能操作,中间div可以操作
  • 原文地址:https://www.cnblogs.com/lykxbg/p/13650380.html
Copyright © 2020-2023  润新知