序列java中的服务(线程)

时间:2013-03-21 12:35:38

标签: java multithreading service

我的任务是相互依赖3(A,B,C)服务。当服务A启动时,服务B可以启动,当服务B启动时,服务C可以启动,当C停止时,B可以停止,当B停止时A可以停止。 我已经设法启动线程并使用status选项从一个切换到另一个。我不得不说,我不知道关于java的这么多东西,但我刚开始学习java所以我是新的,所以任何帮助,建议等都会很棒。

此外,我有3个几乎相同的类,所以任何人都可以告诉他们如何用一个替换这3个类?有什么办法吗?

这是我的代码:

public class service_class {
    int status=1;
    public static void main(String[] args) {

        service_class service_class = new service_class();

        A1 a=new A1(service_class);
        B1 b=new B1(service_class);
        C1 c=new C1(service_class);

        a.start();
        b.start();
        c.start();

    }
}

class A1 extends Thread{
    service_class service_class;

    A1(service_class service_class){
        this.service_class = service_class;
    }


    @Override
    public void run() {

        try{
            synchronized (service_class) {
                 while(service_class.status!=1){
                        service_class.wait();
                    }

                    System.out.print("A started" + "\n");
                    service_class.status = 2;
                    service_class.notifyAll();

                    while(service_class.status!=7){
                        service_class.wait();
                    }
                    System.out.print("A stoped" + "\n");
                    service_class.status = 1;
                    service_class.notifyAll();
                }

        }catch (Exception e) {
            System.out.println("Exception 1 :"+e.getMessage());
        }

    }

}

class B1 extends Thread{

    service_class service_class;

    B1(service_class service_class){
        this.service_class = service_class;
    }

    @Override
    public void run() {

        try{
            synchronized (service_class) {

                    while(service_class.status!=2){
                        service_class.wait();
                    }

                    System.out.print("B started " + "\n");
                    service_class.status = 4;
                    service_class.notifyAll();

                    while(service_class.status!=6){
                        service_class.wait();
                    }
                    System.out.print("B stoped" + "\n");
                    service_class.status = 7;
                    service_class.notifyAll();
                }

        }catch (Exception e) {
            System.out.println("Exception 2 :"+e.getMessage());
        }

    }
}


class C1 extends Thread{

    service_class service_class;

    C1(service_class service_class){
        this.service_class = service_class;
    }

    @Override
    public void run() {

        try{
            synchronized (service_class) {
                 while(service_class.status!=4){
                        service_class.wait();
                    }
                    System.out.print("C started" + "\n");
                    service_class.status = 5;
                    service_class.notifyAll();

                    while(service_class.status!=5){
                        service_class.wait();
                    }
                    System.out.print("C stoped" + "\n");
                    service_class.status = 6;
                    service_class.notifyAll();
            }
        }catch (Exception e) {
            System.out.println("Exception 4 :"+e.getMessage());
        };

    }
}

3 个答案:

答案 0 :(得分:3)

  

我有3个几乎相同的类,所以任何人都可以告诉他们如何用一个替换这3个类?有什么办法吗?

看来3个类ABC之间的差异是:

  • 要打印的名称字符串,
  • 每个人测试和设置的状态值。

所以只需用final个实例变量替换它们,并用传递给(统一)类构造函数的值初始化它们。


然而......

通常认为扩展Thread是一个坏主意。首先,它使得难以使用线程池。更好的方法是使用标准Thread类,并在构造它时将其传递给Runnable实例。实际上,如果您正在使用线程池或Executor服务或其他任何东西,您甚至不需要自己创建和管理线程。

对于等待/通知内容,使用更高级别的同步构造(例如CountDownLatch)更容易。

答案 1 :(得分:1)

使用CountDownLatch

使用给定计数初始化CountDownLatchawait方法阻塞,直到计数达到零,这是由于countDown()方法(由其他线程)的调用,之后所有等待的线程都被释放。我的建议是编写一个超类:

  • 提供初始计数为1
  • 的锁存器
  • 接受该类的另一个实例或在执行前等待的CountDownLatch
  • 在启动时减少其锁定
  • 将该逻辑包装在run中,并提供一个抽象方法innerRun,其中将实现实际代码。

    abstract class LatchedRunnable extends Runnable {
    
    private CountDownLatch latch=new CountDownLatch(1);
    private CountDownLatch wait;
    public Foo(LatchedRunnable waitFor) {
      this.wait=waitFor.latch;
    }
    public Foo(CountDownLatch waitFor) {
      this.wait=waitFor;
    }
    
    final run () {
     //wait for the other thread
     if (wait!=null) 
        try {wait.await();} 
        catch (InterruptedException e) {return;}
    
     //signal that we have started
     latch.countDown();
    
     //actually start
     innerRun();
    }
    
    protected abstract void innerRun(); //do stuff here
    }
    
    
    
    class Foo extends LatchedRunnable {
       Foo(LatchedRunnable waitFor) {super(waitFor);}
       protected void innerRun() {...}
    }
    
    class Bar extends LatchedRunnable { 
       Bar(LatchedRunnable waitFor) {super(waitFor);}
       protected void innerRun() {...}
    }
    
    Foo foo = new Foo(null);
    Bar bar = new Bar(foo);
    

答案 2 :(得分:0)

根据我的理解,

CountDownLatch是一种在不进入死锁的情况下实现同步的机制。所以在这里,

考虑一下,Thread1执行一个文件读取等任务。一旦读取完整文件,另一个线程就可以处理文件内容并获取某些信息。现在第三个线程负责将信息复制到DB。

假设有多个客户端使用上述相同的步骤并且顺序相同:

  1. FILEREAD
  2. FileProcessor
  3. 的dbupdate
  4. 我们不是按顺序处理所有内容,而是创建三个线程池。

    ThreadPool<FileReaderThread> poolA;
    ThreadPool<FileProcessorThread> poolB;
    ThreadPool<DBUpdate> poolC;
    

    随着新请求的进入,将创建一个具有适当计数的倒计时。当poolA中的线程完成其工作时,计数将递减。一旦此计数达到0,将调用来自poolB的线程。类似地,另一个countdownlatch将用于同步来自poolB和poolC的线程。理想情况下,我们使用CountDownLatch实现顺序过程。

    如果出现问题,请更正。