�用关键字synchronized声明方法在某些情况下是有弊端的,比如A线程调用同步方法执行一个长时间的任务,那么B线程则必须等待比较长时间,在这样的情况下可以使用synchronized同步代码块来解决。
package other.thread3;
import java.util.ArrayList;
import java.util.List;
/**
* 只能放一个元素的List
* @author xml
*
*/
public class MyOneList {
private List<String> list = new ArrayList<>();
public synchronized void add(String data) {
list.add(data);
}
public synchronized Integer getSize() {
return list.size();
}
}
package other.thread3;
public class MyService {
public MyOneList addServiceMethod(MyOneList list,String data) {
try {
if(list.getSize() < 1) {
Thread.sleep(2000);
list.add(data);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return list;
}
}
package other.thread3;
public class ThreadA extends Thread {
private MyOneList list;
public ThreadA(MyOneList list) {
this.list = list;
}
@Override
public void run() {
MyService service = new MyService();
service.addServiceMethod(list, "AAAA");
}
}
package other.thread3;
public class ThreadB extends Thread {
private MyOneList list;
public ThreadB(MyOneList list) {
this.list = list;
}
@Override
public void run() {
MyService service = new MyService();
service.addServiceMethod(list, "BBBB");
}
}
package other.thread3;
public class Test {
public static void main(String[] args) throws InterruptedException {
MyOneList list = new MyOneList();
ThreadA threadA = new ThreadA(list);
threadA.start();
ThreadB threadB = new ThreadB(list);
threadB.start();
Thread.sleep(3000);
System.out.println("getSize" + list.getSize());
}
}

'脏读'出现了,出现的原因是两个线程在addServiceMethod方法中异步的返回list参数的大小,解决的办法就是同步化。
package other.thread3;
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) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return list;
}
}
由于list参数对象在项目中是一份实例,是单例的,而且也正需要对list参数的getSize()方法做同步的调用,所以就对list参数进行同步处理。
网友评论