0

我的任务是使 3 个(A、B、C)服务相互依赖。当服务A启动时,服务B可以启动,当服务B启动时,服务C可以启动,当C停止时,B可以停止,当B停止时,A可以停止。我已经设法启动线程并使用状态选项从一个切换到另一个。我不得不说我对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());
        };

    }
}
4

3 回答 3

3

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

看起来这 3 个类之间的A区别BC

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

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


然而 ...

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

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

于 2013-03-21T12:45:11.473 回答
1

使用CountDownLatch

ACountDownLatch用给定的计数初始化。该await方法会阻塞,直到由于该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);
    
于 2013-03-21T12:39:09.580 回答
0

CountDownLatch,在我的理解中,是一种在不进入死锁的情况下实现同步的机制。就这样,

考虑一下,Thread1 执行诸如文件读取之类的任务。读取完整文件后,另一个线程可以处理文件内容并获取某些信息。现在第三个线程负责将信息复制到数据库。

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

  1. 文件读取
  2. 文件处理器
  3. 数据库更新

我们不是按顺序处理所有事情,而是创建三个线程池。

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

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

如有不妥请指正。

于 2015-02-04T09:46:14.933 回答