我现在有一个这样的资源类,可能的方法如下所示
class A {
List test;
set(); // 初始化test,并赋值
reset(); // 请空test,并对test重新赋值
get(int index); // 取test中的某个值
}
一般情况下test初始化后有多个线程会调用get()方法取值,为了保证效率也不需要同步get()方法,但一定概率下会有其他线程对test调用reset()方法,我的需求是:当有线程调用reset()方法时(同一时刻只有一个线程调用reset()),其他线程再调用get()时,必须等待reset()结束后,方可继续。主要是避免读取错误!我想请问一下大家谁有比较好的解决方案?
为什么呢?
下面是我机器上的执行结果
Thread-0执行get(int i)
Thread-0执行get(int i)
Thread-1执行get(int i)
Thread-0正在执行reset()
Thread-0reset()执行完毕
Thread-1执行get(int i)
Thread-1执行get(int i)
Thread-1执行get(int i)
Thread-1执行get(int i)
Thread-1执行get(int i)
Thread-1正在执行reset()
Thread-1reset()执行完毕
Thread-1执行get(int i)
Thread-0执行get(int i)
Thread-0执行get(int i)
Thread-0执行get(int i)
Thread-0执行get(int i)
Thread-0执行get(int i)
Thread-0执行get(int i)
Thread-0执行get(int i)
Thread-0执行get(int i)
Thread-0执行get(int i)
Thread-0执行get(int i)
Thread-0执行get(int i)
Thread-0执行get(int i)
Thread-0执行get(int i)
Thread-0执行get(int i)
Thread-0执行get(int i)
Thread-0执行get(int i)
Thread-0执行get(int i)
Thread-1执行get(int i)
Thread-1执行get(int i)
Thread-1执行get(int i)
Thread-1正在执行reset()
Thread-1reset()执行完毕
Thread-1执行get(int i)
Thread-1执行get(int i)
Thread-1执行get(int i)
Thread-1执行get(int i)
Thread-1执行get(int i)
Thread-1执行get(int i)
Thread-1执行get(int i)
Thread-1执行get(int i)
分析一下上面的结果:
Thread-1正在执行reset()
Thread-1reset()执行完毕
之间没有任何的get(int i)操作,可是在reset()方法中,线程要sleep(5000),这么长的时间,其他的线程都没有执行get(int i)操作,这不是你的要求吗?
你也可以把sleep的时间设置成更长的时间,在reset方法执行完之前,其他的线程是不能get方法的
import java.util.List;
class Test1 {
List test;
boolean isLocked =false;
void set() {
}
synchronized void reset() {
isLocked = true;
System.out.println("start this is reset");
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/*****/
System.out.println("end this is reset");
isLocked = false;
}
int get(int index) {
//这里等待reset()执行完。
while (isLocked) {
System.out.println("00000000000");
}
return index;
}
public static void main(String[] args) {
final Test1 t = new Test1();
new Thread(new Runnable(){
public void run(){
t.reset();
}
}).start();
new Thread(new Runnable(){
public void run(){
System.out.println("ssssssssss:"+t.get(0));
}
}).start();
}
}
只要简单的在reset()方法中加入以下代码:
reset(){
synchronized(this){
// 这里添加功能
// 请空test,并对test重新赋值
}
}
下面的代码为验证想法的一个代码
import java.util.ArrayList;
import java.util.List;
class A {
private List<String> lists = new ArrayList<String>();
public A() {
lists.add("张三");
lists.add("李四");
}
public void reset() {
synchronized (this) {
System.out.println(Thread.currentThread().getName() + "正在执行reset()");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
lists.clear();
lists.add("张三");
lists.add("李四");
System.out.println(Thread.currentThread().getName() + "reset()执行完毕");
}
}
public synchronized String get(int i) {
System.out.println(Thread.currentThread().getName() + "执行get(int i)");
return lists.get(i);
}
}
class TestThread extends Thread {
private A a = null;
public TestThread(A a) {
this.a = a;
}
@Override
public void run() {
// TODO Auto-generated method stub
int loop = 20;
while (loop > 0) {
loop--;
if ((int) (Math.random() * 10) == 1) {
a.reset();
} else {
a.get(1);
}
}
}
}
public class T1 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
A a = new A();
TestThread t1 = new TestThread(a);
TestThread t2 = new TestThread(a);
TestThread t3 = new TestThread(a);
TestThread t4 = new TestThread(a);
t1.start();
t2.start();
// t3.start();
// t4.start();
}
}