假设有一个base类:
public abstract class Base(){
public abstract String doTask();
}
两个子类:public class Child1() extends Base{
public String doTask(){};
}
public class Child2() extends Base{
public String doTask(){};
}
假如我想实现一个功能,在运行子类1的dotask方法前,判断是否已经存在一个线程正在执行子类1的dotask方法,如果存在,就return,如果不存在就执行dotask。对与子类2,同样判断是否有一个线程正在执行子类2的dotask方法,如果存在就return,如果不存在就执行。我的实现是在子类中定义一个static变量,用synchronize块修改和判断,来保证当前类只存在一个线程执行dotask方法。但是我感觉这些方法在每个子类里面都重复,我想把它放到父类里面。但是在父类里面却不能访问子类的字段,只能保证所有子类只有一个执行,而不是每一个子类只有一个执行。有没好方法实现这个功能?

解决方案 »

  1.   

    这个思路的方向似乎有点不对,你的意思我不知道可不可以理解成:一个实例对象,如果有一个线程访问过该对象的XX方法,那么以后访问该方法的直接return?
    这个不能从本类上考虑,那样必然会给该类,增加不必要的功能和责任。
    我觉得可以建一个代理类,通过代理来实现你的这些判断功能,当然,也可以采用动态代理,这样不必为每个类新建代理类。
      

  2.   

    现在子类的实现是:
    public class Child1() extends Base{
    public static Boolean running = false; public String doTask(long arg0) throws Exception {
    synchronized (running) {
    if (running == true) {
    return "There is a task is still running , current task is ignored .";
    }
    running = true;
    }
    try {
    String result = doMyTask();
    return result;
    } catch (Exception e) {
    throw e;
    } finally {
    synchronized (running) {
    running = false;
    }
    }
    }
    }不是类child1一个实例对象,可以同时有多个child1的实例对象。假设有一个线程正在调用任何一个对象的那个方法,那么其他的线程再调用的时候就直接return。但同时,child2的调用不受child1影响。也是可以有多个child2类,但同一时间只允许一个线程正常执行child2方法。
    为什么想用一个父类,因为这些逻辑判断都是相同的。在子类中进行判断没有问题,但是代码冗余很严重。在父类中进行判断,会使child1和child2所有子类中只能有一个正常运行,而不是child1有一个正常运行,child2有一个正常运行了。
    希望java里面能有一个abstract的field。那我就可以在父类中synchronize子类中的field对象了。。
      

  3.   

    无需显式同步,如此即可:public abstract class Base(){
    protected AtomicBoolean executing = new AtomicBoolean();

    public final String doTask() {
    if(executing.compareAndSet(false, true)) {
    try {
    doTask0();
    } finally {
    executing.set(false);
    }
    }
    }

    public abstract doTask0();
    }
    public class Child1() extends Base{
    public String doTask0(){};
    }public class Child2() extends Base{
    public String doTask0(){};
    }
      

  4.   


    不行,这样当两个线程同时调用child的时候,两个进程同时执行了task方法。
      

  5.   


    虽然会同时进入 task() ,但这句话会保证只有1个线程会执行里面的代码:
      if(executing.compareAndSet(false, true)) {
    如果你需要的话,也可以把这句话搬到 Child12这里来。
      

  6.   


    因为我不想搬到子类当中才想放到BASE类中。现在对于6楼的回复,由于executing不是static类型的,如果这样调用的话就不能实现同步了:public void main(String args[]){
    final Base b1 = new Child1();
    Base b2 = new Child2();
    new Thread(){
    public void run(){
    b1.doTask();
    }
    }.start();
    b2.doTask();
    }
      

  7.   

    找到解决方法了!
    package test;public abstract class Father {
    public void test() {
    System.out.println(Thread.currentThread().getName() + " thread come to test ..");
    synchronized (this.getClass()) {
    execute();
    }
    System.out.println(Thread.currentThread().getName() + " thread end to test ..");
    } protected abstract void execute();
    }
    package test;public class Child extends Father {
    public static void main(String[] args) throws InterruptedException {
    new Thread("child Thread ") {
    public void run() {
    Father test = new Child();
    test.test();
    }
    }.start();
    Thread.sleep(1000);
    new Thread("child2 Thread ") {
    public void run() {
    Father test = new Child2();
    test.test();
    }
    }.start();
    new Thread("2ed child Thread ") {
    public void run() {
    Father test = new Child();
    test.test();
    }
    }.start();
    } @Override
    protected void execute() {
    System.out.println(Thread.currentThread().getName() + " execute in child ... sleep ...");
    try {
    Thread.sleep(4000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName() + "execute in child finished ...");
    }
    }
    package test;public class Child2 extends Father {
    @Override
    protected void execute() {
    System.out.println(Thread.currentThread().getName() + " execute in child2 ... sleep ...");
    try {
    Thread.sleep(3000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName() + "execute in child2 finished ...");
    }
    }用Child类中的main方法运行结果:child Thread  thread come to test ..
    child Thread  execute in child ... sleep ...
    2ed child Thread  thread come to test ..
    child2 Thread  thread come to test ..
    child2 Thread  execute in child2 ... sleep ...
    child Thread execute in child finished ...
    2ed child Thread  execute in child ... sleep ...
    child Thread  thread end to test ..
    child2 Thread execute in child2 finished ...
    child2 Thread  thread end to test ..
    2ed child Thread execute in child finished ...
    2ed child Thread  thread end to test ..
    自己找到的java同步规律:
     syn(this) == normal syn method , but prefer syn method. 
     static syn method == syn(xxx.getClass). static syn method can be used good .
     It’s good to use wait and notify when using syn.