将任意对象作为对象监视器

synchronized同步代码块还支持任意对象,使用格式为synchronized(非this对象)

package Second;

public class Service {

    private String usernameParam;
private String passwordParam;
 private String anyString =  new String();
public void setUsernamePassword(String username, String password) {
try {
synchronized (anyString) {
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "进入同步块");
usernameParam = username;
Thread.sleep(3000);
passwordParam = password;
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "离开同步块");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }
package Second;

public class ThreadA extends Thread {
private Service service; public ThreadA(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.setUsernamePassword("a", "aa"); } }
package Second;

public class ThreadB extends Thread {

    private Service service;

    public ThreadB(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.setUsernamePassword("b", "bb"); } }
package Second;

public class Run {

    public static void main(String[] args) {
Service service = new Service(); ThreadA a = new ThreadA(service);
a.setName("A");
a.start(); ThreadB b = new ThreadB(service);
b.setName("B");
b.start(); } }

package Second;

public class Service {

    private String usernameParam;
private String passwordParam;
public void setUsernamePassword(String username, String password) {
try {
String anyString = new String();
synchronized (anyString) {
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "进入同步块");
usernameParam = username;
Thread.sleep(3000);
passwordParam = password;
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "离开同步块");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }

package Second;

public class Service {

    private String anyString = new String();

    public void a() {
try {
synchronized (anyString) {
System.out.println("a begin");
Thread.sleep(3000);
System.out.println("a end");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} synchronized public void b() {
System.out.println("b begin");
System.out.println("b end");
} }
package Second;

public class ThreadA extends Thread {
private Service service; public ThreadA(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.a(); } }
package Second;

public class ThreadB extends Thread {

    private Service service;

    public ThreadB(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.b(); } }
package Second;

public class Run {

    public static void main(String[] args) {
Service service = new Service(); ThreadA a = new ThreadA(service);
a.setName("A");
a.start(); ThreadB b = new ThreadB(service);
b.setName("B");
b.start(); } }

由于对象监视器不同,所以运行结果就是异步的

下面验证多个线程调用同一个方法是随机的

package Second;

import java.util.ArrayList;
import java.util.List; public class MyList { private List list = new ArrayList(); synchronized public void add(String username) {
System.out.println("ThreadName=" + Thread.currentThread().getName()
+ "执行了add方法!");
list.add(username);
System.out.println("ThreadName=" + Thread.currentThread().getName()
+ "退出了add方法!");
} synchronized public int getSize() {
System.out.println("ThreadName=" + Thread.currentThread().getName()
+ "执行了getSize方法!");
int sizeValue = list.size();
System.out.println("ThreadName=" + Thread.currentThread().getName()
+ "退出了getSize方法!");
return sizeValue;
} }
package Second;

public class MyThreadA extends Thread {

    private MyList list;

    public MyThreadA(MyList list) {
super();
this.list = list;
} @Override
public void run() {
for (int i = 0; i < 100000; i++) {
list.add("threadA" + (i + 1));
}
} }
package Second;

public class MyThreadB extends Thread {

    private MyList list;

    public MyThreadB(MyList list) {
super();
this.list = list;
} @Override
public void run() {
for (int i = 0; i < 100000; i++) {
list.add("threadB" + (i + 1));
}
}
}
package Second;

public class Test {

    public static void main(String[] args) {
MyList mylist = new MyList(); MyThreadA a = new MyThreadA(mylist);
a.setName("A");
a.start(); MyThreadB b = new MyThreadB(mylist);
b.setName("B");
b.start();
} }

下面展示多线程出现脏读的情况

package Second;

import java.util.ArrayList;
import java.util.List; public class MyOneList { private List list = new ArrayList(); synchronized public void add(String data) {
list.add(data);
}; synchronized public int getSize() {
return list.size();
}; }
package Second;

public class MyService {

    public MyOneList addServiceMethod(MyOneList list, String data) {
try {
synchronized (list) {
if (list.getSize() < 1) {
Thread.sleep(2000);
list.add(data);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return list;
} }
package Second;

public class MyThread1 extends Thread {

    private MyOneList list;

    public MyThread1(MyOneList list) {
super();
this.list = list;
} @Override
public void run() {
MyService msRef = new MyService();
msRef.addServiceMethod(list, "A");
} }
package Second;

public class MyThread2 extends Thread {

    private MyOneList list;

    public MyThread2(MyOneList list) {
super();
this.list = list;
} @Override
public void run() {
MyService msRef = new MyService();
msRef.addServiceMethod(list, "B");
} }
package Second;

public class Run {

    public static void main(String[] args) throws InterruptedException {
MyOneList list = new MyOneList(); MyThread1 thread1 = new MyThread1(list);
thread1.setName("A");
thread1.start(); MyThread2 thread2 = new MyThread2(list);
thread2.setName("B");
thread2.start(); Thread.sleep(6000); System.out.println("listSize=" + list.getSize()); } }

"脏读"出现了。出现的原因是两个线程以异步的方式返回list参数的size()大小。解决办法是“”同步化

package Second;

public class MyService {

    public MyOneList addServiceMethod(MyOneList list, String data) {
try {
synchronized (list) {
if (list.getSize() < 1) {
Thread.sleep(2000);
list.add(data);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return list;
} }

由于list参数对象在项目中是一份实例,是单例的,而且也正需要对list参数的getsize()方法做同步的调用,所以就对list参数进行同步处理

最新文章

  1. R语言——绘制半圆形图
  2. [Android]从Launcher开始启动App流程源码分析
  3. oracle 修改密码
  4. 几个CSS3动画
  5. SVN服务端启动解决方案(2013-12-10 记)
  6. [leetcode] Contains Duplicate
  7. Web 在线文件管理器学习笔记与总结(19)上传文件
  8. iOS中使用子线程的完整方法
  9. 再谈PCA
  10. 【C#学习笔记】类型转换
  11. asp.net mvc jqgrid 同一个页面查询不同的表,jqgrid显示不同表的表头和数据并且分页
  12. poj 3259 Wormholes【spfa判断负环】
  13. WCF、Web API、WCF REST、Web Service 区别
  14. iOS 开发之Target-action模式
  15. powershell V6.0登基之:《瘸腿脚本大帝进攻linux!》
  16. Nginx正向代理与反向代理
  17. grep&#160;-v、-e、-E
  18. Springboot+MyBatis+JPA集成
  19. 洛谷P1600 天天爱跑步
  20. Scala基础(1)

热门文章

  1. FPGA学习记录 - Quartus II 未使用管脚设置为三态输入
  2. 【BZOJ4976】宝石镶嵌 DP
  3. input file 选择Excel
  4. (Android)react-native-splash-screen实践-解决react-native打包好后启动白屏的问题
  5. win7下搭建nginx+php的开发环境(转)
  6. es6技巧写法
  7. Adding Form Fields to a MS Word Document
  8. Hive- Hive Web Interface
  9. javascript(9)
  10. 分享知识-快乐自己:Excel快速导入Oracle 数据库