13、synchronized同步代码块

版权声明:版权归 爱装逼的文艺小青年所有 https://blog.csdn.net/toyota_rav4/article/details/84963372

synchronized同步方法的弊端

当A线程调用对象中的同步方法时执行任务的时间很长,这样B线程要一直晾着,啥事也干不了。这就是弊端!

假设A,B,C,D等多位顾客正在超市收银台结账,A正在结账的时候发现自己钱没带,需要回家去拿,剩下的顾客如果一直等着A回家拿完钱结完账才能买单,那就很耽误后面顾客的时间。这时候应该让后面的人结账走人。

放到线程中就是 A线程任务花费时间长,应该让其他线程先执行。

package com.demo15;

import java.text.SimpleDateFormat;

public class MyObject {
    synchronized public void myTaskA(){
        try {
            System.out.println("myTaskA");
            System.out.println("myTaskA即将进入睡眠,时间=" +
                    SimpleDateFormat.getDateTimeInstance().format(System.currentTimeMillis()));
            Thread.sleep(5000);
            System.out.println("myTaskA即将结束睡眠,时间=" +
                    SimpleDateFormat.getDateTimeInstance().format(System.currentTimeMillis()));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    synchronized public void myTaskB(){
        System.out.println("myTaskB");
    }
}
package com.demo15;

public class ThreadA extends Thread {
    MyObject myObject = new MyObject();

    public ThreadA(MyObject myObject) {
        this.myObject = myObject;
    }

    @Override
    public void run() {
        myObject.myTaskA();
    }
}
package com.demo15;

public class ThreadB extends Thread {
    MyObject myObject = new MyObject();

    public ThreadB(MyObject myObject) {
        this.myObject = myObject;
    }

    @Override
    public void run() {
        myObject.myTaskB();
    }
}
package com.demo15;

import java.text.SimpleDateFormat;

public class Run {
    public static String begintime ;
    public static void main(String[] args) {
        MyObject myObject = new MyObject();
        ThreadA threadA = new ThreadA(myObject);
        ThreadB threadB = new ThreadB(myObject);
        threadA.start();
        threadB.start();
    }
}

运行结果:

myTaskA
myTaskA即将进入睡眠,时间=2018-12-11 23:06:21
myTaskA即将结束睡眠,时间=2018-12-11 23:06:26
myTaskB

通过结果可知,A执行同步方法花费了5秒,这期间B什么也不能做!

作出以下的修改:

package com.demo15;

import java.text.SimpleDateFormat;

public class MyObject {
    public void myTaskA(){
        try {
            synchronized(this){
                System.out.println("myTaskA");
            }
            System.out.println("myTaskA即将进入睡眠,时间=" +
                    SimpleDateFormat.getDateTimeInstance().format(System.currentTimeMillis()));
            Thread.sleep(5000);
            System.out.println("myTaskA即将结束睡眠,时间=" +
                    SimpleDateFormat.getDateTimeInstance().format(System.currentTimeMillis()));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    synchronized public void myTaskB(){
        System.out.println("myTaskB");
    }
}

此时的运行结果为:

myTaskA
myTaskB
myTaskA即将进入睡眠,时间=2018-12-11 23:20:05
myTaskA即将结束睡眠,时间=2018-12-11 23:20:10

当A执行完同步代码块之后,立即释放锁,让其他线程执行!然后再获取CPU资源来运行后续的花费事件长的任务。

通过上面的例子我们可以看到 使用同步代码块 相对使用同步方法的优势!

猜你喜欢

转载自blog.csdn.net/toyota_rav4/article/details/84963372
今日推荐