Java多线程编程核心技术(第3版)
上QQ阅读APP看书,第一时间看更新

2.2.1 synchronized方法的弊端

为了证明用synchronized关键字声明方法时是有弊端的,下面创建t5项目来进行测试。

文件Task.java代码如下:


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();
    }
}
}

用synchronized声明方法时,放在public之后与放在public之前没有区别。

文件CommonUtils.java代码如下:


package commonutils;

public class CommonUtils {

public static long beginTime1;
public static long endTime1;

public static long beginTime2;
public static long endTime2;
}

文件MyThread1.java代码如下:


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();
}

}

文件MyThread2.java代码如下:


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();
}

}

文件Run.java代码如下:


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));
}
}

程序运行结果如图2-20所示。

图2-20 大约6秒后程序运行结束

通过使用synchronized关键字来声明方法,从运行的时间上来看,弊端突现,可以使用synchronized同步块解决类似问题。