java多线程基本概述(三)——同步块

1.1、synchronized方法的弊端

package commonutils;

public class CommonUtils {

    public static long beginTime1;
    public static long endTime1;

    public static long beginTime2;
    public static long endTime2;
}

=============================
package mytask;

import commonutils.CommonUtils;

public class Task {

    private String getData1;
    private String getData2;

    public synchronized void doLongTimeTask() {
        try {
            System.out.println("begin task");
            Thread.sleep(3000);
            getData1 = "长时间处理任务后从远程返回的值1 threadName="
                    + Thread.currentThread().getName();
            getData2 = "长时间处理任务后从远程返回的值2 threadName="
                    + Thread.currentThread().getName();
            System.out.println(getData1);
            System.out.println(getData2);
            System.out.println("end task");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
=======================================
package mythread;

import commonutils.CommonUtils;

import mytask.Task;

public class MyThread1 extends Thread {

    private Task task;

    public MyThread1(Task task) {
        super();
        this.task = task;
    }

    @Override
    public void run() {
        super.run();
        CommonUtils.beginTime1 = System.currentTimeMillis();
        task.doLongTimeTask();
        CommonUtils.endTime1 = System.currentTimeMillis();
    }

}
=============================================
package mythread;

import commonutils.CommonUtils;

import mytask.Task;

public class MyThread2 extends Thread {

    private Task task;

    public MyThread2(Task task) {
        super();
        this.task = task;
    }

    @Override
    public void run() {
        super.run();
        CommonUtils.beginTime2 = System.currentTimeMillis();
        task.doLongTimeTask();
        CommonUtils.endTime2 = System.currentTimeMillis();
    }

}
package test;

import mytask.Task;
import mythread.MyThread1;
import mythread.MyThread2;

import commonutils.CommonUtils;

public class Run {

    public static void main(String[] args) {
        Task task = new Task();

        MyThread1 thread1 = new MyThread1(task);
        thread1.start();

        MyThread2 thread2 = new MyThread2(task);
        thread2.start();

        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        long beginTime = CommonUtils.beginTime1;
        if (CommonUtils.beginTime2 < CommonUtils.beginTime1) {
            beginTime = CommonUtils.beginTime2;
        }

        long endTime = CommonUtils.endTime1;
        if (CommonUtils.endTime2 > CommonUtils.endTime1) {
            endTime = CommonUtils.endTime2;
        }

        System.out.println("耗时:" + ((endTime - beginTime) / 1000));
    }
}

输出结果:

begin task
长时间处理任务后从远程返回的值1 threadName=Thread-0
长时间处理任务后从远程返回的值2 threadName=Thread-0
end task
begin task
长时间处理任务后从远程返回的值1 threadName=Thread-1
长时间处理任务后从远程返回的值2 threadName=Thread-1
end task
耗时:6

当把同步方法改为同步代码块时,

package mytask;

import commonutils.CommonUtils;

public class Task {

    private String getData1;
    private String getData2;

    public  void doLongTimeTask() {
        synchronized(Task.class){
            try {
                System.out.println("begin task");
                Thread.sleep(3000);
                getData1 = "长时间处理任务后从远程返回的值1 threadName="
                        + Thread.currentThread().getName();
                getData2 = "长时间处理任务后从远程返回的值2 threadName="
                        + Thread.currentThread().getName();
                System.out.println(getData1);
                System.out.println(getData2);
                System.out.println("end task");
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
    }
}

输出结果:

begin task
长时间处理任务后从远程返回的值1 threadName=Thread-0
长时间处理任务后从远程返回的值2 threadName=Thread-0
end task
begin task
长时间处理任务后从远程返回的值1 threadName=Thread-1
长时间处理任务后从远程返回的值2 threadName=Thread-1
end task
耗时:6

可见,并没有提升效率,这是因为锁定的范围比较广,所以效果和锁方法的差别并不是太。那么可以缩小边界区,也就是资源真正开始竞争的地方。因为类中的成员变量才是资源的竞争对象,所以需要在访问这些变量的地方进行锁定。那么代码改为如下:

package mytask;

import commonutils.CommonUtils;

public class Task {

    private String getData1;
    private String getData2;

    public  void doLongTimeTask() {
        
            try {
                System.out.println("begin task");
                Thread.sleep(3000);
                getData1 = "长时间处理任务后从远程返回的值1 threadName="
                        + Thread.currentThread().getName();
                getData2 = "长时间处理任务后从远程返回的值2 threadName="
                        + Thread.currentThread().getName();
                synchronized(Task.class){
                    System.out.println(getData1);
                    System.out.println(getData2);
                }
                System.out.println("end task");
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }    
    }
}

输出结果:

begin task
begin task
长时间处理任务后从远程返回的值1 threadName=Thread-0
长时间处理任务后从远程返回的值2 threadName=Thread-0
end task
长时间处理任务后从远程返回的值1 threadName=Thread-1
长时间处理任务后从远程返回的值2 threadName=Thread-1
end task
耗时:3

这时候可以看到时间已经减小了,这就出现一部分同步,一部分异步了。如何验证是真的一半同步一半异步呢?

package mytask;

public class Task {

    public void doLongTimeTask() {
        for (int i = 0; i < 100; i++) {
            System.out.println("nosynchronized threadName="
                    + Thread.currentThread().getName() + " i=" + (i + 1));
        }
        System.out.println("");
        synchronized (this) {
            for (int i = 0; i < 100; i++) {
                System.out.println("synchronized threadName="
                        + Thread.currentThread().getName() + " i=" + (i + 1));
            }
        }

    }
}

输出结果:

=================================非同步块异步执行
nosynchronized threadName=Thread-0 i=1
nosynchronized threadName=Thread-1 i=1
nosynchronized threadName=Thread-0 i=2
nosynchronized threadName=Thread-1 i=2
nosynchronized threadName=Thread-0 i=3
nosynchronized threadName=Thread-1 i=3
nosynchronized threadName=Thread-0 i=4
nosynchronized threadName=Thread-1 i=4
nosynchronized threadName=Thread-0 i=5
nosynchronized threadName=Thread-1 i=5
nosynchronized threadName=Thread-0 i=6
nosynchronized threadName=Thread-1 i=6
nosynchronized threadName=Thread-0 i=7
nosynchronized threadName=Thread-1 i=7
nosynchronized threadName=Thread-0 i=8
nosynchronized threadName=Thread-1 i=8
=================================同步块同步执行
synchronized threadName=Thread-1 i=85
synchronized threadName=Thread-1 i=86
synchronized threadName=Thread-1 i=87
synchronized threadName=Thread-1 i=88
synchronized threadName=Thread-1 i=89
synchronized threadName=Thread-1 i=90
synchronized threadName=Thread-1 i=91
synchronized threadName=Thread-1 i=92
synchronized threadName=Thread-1 i=93
synchronized threadName=Thread-1 i=94
synchronized threadName=Thread-1 i=95
synchronized threadName=Thread-1 i=96
synchronized threadName=Thread-1 i=97
synchronized threadName=Thread-1 i=98
synchronized threadName=Thread-1 i=99
synchronized threadName=Thread-1 i=100
synchronized threadName=Thread-0 i=1
synchronized threadName=Thread-0 i=2
synchronized threadName=Thread-0 i=3
synchronized threadName=Thread-0 i=4
synchronized threadName=Thread-0 i=5
synchronized threadName=Thread-0 i=6
synchronized threadName=Thread-0 i=7
synchronized threadName=Thread-0 i=8
synchronized threadName=Thread-0 i=9
synchronized threadName=Thread-0 i=10
synchronized threadName=Thread-0 i=11
synchronized threadName=Thread-0 i=12
synchronized threadName=Thread-0 i=13
synchronized threadName=Thread-0 i=14
synchronized threadName=Thread-0 i=15
synchronized threadName=Thread-0 i=16

 

posted @ 2017-04-17 17:19  soar_hu  阅读(165)  评论(0编辑  收藏  举报