如何使用一个Java程序来监视另一个Java程序';谁的产量?

如何使用一个Java程序来监视另一个Java程序';谁的产量?,java,multithreading,io,processbuilder,Java,Multithreading,Io,Processbuilder,下面的图表显示了我正在尝试做的事情:它只是两个程序。一个是一个简单的Child程序,它每2秒逐行写出整数 另一个是监控日志文件(只是一个非常基本的文本文件)的Parent程序。如果日志文件在5秒内未被修改,则应重新启动子程序程序(通过批处理文件);然后正常继续 我的子类代码如下: package fileiotestapplication; import java.io.*; import java.io.IOException; import java.util.*; public cl

下面的图表显示了我正在尝试做的事情:它只是两个程序。一个是一个简单的
Child
程序,它每2秒逐行写出整数

另一个是监控日志文件(只是一个非常基本的文本文件)的
Parent
程序。如果日志文件在5秒内未被修改,则应重新启动
子程序
程序(通过批处理文件);然后正常继续

我的子类代码如下:

package fileiotestapplication;
import java.io.*;
import java.io.IOException;
import java.util.*;


public class WriterClass {

    @SuppressWarnings("oracle.jdeveloper.java.insufficient-catch-block")
    public WriterClass() {
        super();


            int[] content = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,};
            String[] friends = {"bob",};

                File file = new File("/C:/Java_Scratch/someFile.txt");
                // if file does not exists, then create it

            try {

                if (!file.exists()) {
                    file.createNewFile();
                }


                for (int i = 0 ; i < content.length; i++) 
                {                   

                        PrintStream bw = new PrintStream( new FileOutputStream(file, true) );     

                        System.out.println("testing " + i);
                        bw.println( String.valueOf(content[i]) );
                        bw.close();


                        Thread.sleep(2500);
                }


                System.out.println("Done");
            } catch (IOException ioe) {
                // TODO: Add catch code
                ioe.printStackTrace();
            }
            catch (InterruptedException ioe) {
                            // TODO: Add catch code
                            ioe.printStackTrace();
                }

        //someIS.println(i);
        System.out.println("This is OK");



    }

    public static void main(String[] args) {
        WriterClass writerClass = new WriterClass();


    }
}

这将变得非常缓慢,因为文件的大小一直在增长。更简单的方法是只检查文件的最后修改时间。假设子程序停止写入文件的原因是程序终止(而不是挂起在无限循环中),那么直接监视子进程本身可能比依赖于观察进程的效果要好。如果父进程可以首先负责启动程序,那么这将特别方便

这可以通过Java8中的和类来完成。从文档中复制,您可以像这样启动流程(如果您只想监视它是否正在运行):


然后,只需调用
p.waitFor()以等待进程终止。在循环中执行此操作,您将自动重新启动子行为。

随着文件大小不断增大,这将变得非常缓慢。更简单的方法是只检查文件的最后修改时间。假设子程序停止写入文件的原因是程序终止(而不是挂起在无限循环中),那么直接监视子进程本身可能比依赖于观察进程的效果要好。如果父进程可以首先负责启动程序,那么这将特别方便

这可以通过Java8中的和类来完成。从文档中复制,您可以像这样启动流程(如果您只想监视它是否正在运行):


然后,只需调用
p.waitFor()以等待进程终止。在循环中执行此操作,您将自动重新启动子行为。

您可以使用目录监视服务:

您可以配置路径或文件,并注册一个
观察者

每次更改文件时,观察者都会收到通知。您可以存储通知的此时间戳以供以后使用

有关详细信息,请参阅上面的我的链接


然后,您可以使用计时器或线程检查上次修改。

您可以使用目录监视服务:

您可以配置路径或文件,并注册一个
观察者

每次更改文件时,观察者都会收到通知。您可以存储通知的此时间戳以供以后使用

有关详细信息,请参阅上面的我的链接


然后,您可以使用计时器或线程来检查上次修改。

虽然您创建文本文件和使用批处理脚本的方法是可行的,但有一种更好的方法可以实现。这是多任务处理的标准问题,通过创建两个线程,一点也不难

与使用批处理文件和多个程序从外部“绕过”系统相比,使用线程有几个优点。首先,这些可能包括:

  • 把所有东西都放在一起会使项目更加整洁, 更容易分发

  • 它更容易实现。当然,如果你从来没有使用过线程,那么线程可能看起来很混乱,但在我看来,它们是较小的邪恶,那么所有涉及到绕过它们的步骤。正如我希望在下面展示的,用线程实现这个问题并不难

  • 提高了性能,因为避免了非常昂贵的文件IO操作和生成批处理文件。在大多数情况下,线程也比进程具有更好的性能,因为它们更容易生成,而多线程比多处理器在更广泛的处理器范围内看到性能的提高,因为它不太依赖多个内核

  • 当一个程序读取文件时,另一个程序同时写入文件时,两者之间没有粗略的重叠。尽可能避免此类情况

  • 保持Java令人印象深刻的跨平台能力,因为您没有使用非跨平台的批处理。对于这个项目来说,这可能并不重要,但将来您可能会遇到类似的问题,这一点更为重要,因此您需要练习如何实现它

  • 通过“正确的方式”使用线程而不是 通过使用更老练的方法养成坏习惯。如果这是一个 学习项目,你最好把它学好

  • 我继续编写了我最有可能用来解决问题的方法。我的代码有一个子线程,每两秒钟计数一次,还有一个父线程监视这个子线程,如果这个子线程五秒钟不计数,就会重新启动它。让我们检查一下我的程序,让您了解它是如何工作的

    首先,这是家长的课程:

    public class Parent {
    
        private Child child;
    
        public Parent(){
            child = new Child(this);
            child.start();
        }
    
        public void report(int count){ //Starts a new watchdog timer
            Watchdog restartTimer = new Watchdog(this, count);
            restartTimer.start();
        }
    
        public void restartChild(int currentCount){
            if (currentCount == child.getCount()){ //Check if the count has not changed
                //If it hasn't
                child.kill();
                child.start();
            }
    
        }
    
    
        public static void main(String[] args){
            //Start up the parent function, it spawns the child
            new Parent();
        }
    
    }
    
    class Watchdog implements Runnable { //A timer that will run after five seconds
           private Thread t;
           private Parent parent;
           private int initialCount;
    
           public Watchdog(Parent parent, int count){ //make a  timer with a count, and access to the parent
               initialCount = count;
               this.parent = parent;
           }
    
           public void run() { //Timers logic
               try {
                   Thread.sleep(5000); // If you want to change the time requirement, modify it here
                   parent.restartChild(initialCount);
    
               } catch (InterruptedException e) {
                    System.out.println("Error in watchdog thread");
                }
    
           }
    
           public void start () // start the timer
           {
              if (t == null)
              {
                 t = new Thread (this);
                 t.start ();
              }
           }
    
        }
    
    如果您愿意,其中的主函数可以放在其他地方,但要启动所有功能,只需实例化一个父函数。父类有子类的一个实例,它启动子线程。子级将使用report方法向父级报告其计数,该方法生成一个看门狗计时器(一秒钟内会有更多内容),该计时器将在五秒钟后使用当前计数调用restartChild。RestartChild,如果计数仍然与提供的计数相同,则重新启动子线程

    下面是看门狗定时器的类:
    public class Parent {
    
        private Child child;
    
        public Parent(){
            child = new Child(this);
            child.start();
        }
    
        public void report(int count){ //Starts a new watchdog timer
            Watchdog restartTimer = new Watchdog(this, count);
            restartTimer.start();
        }
    
        public void restartChild(int currentCount){
            if (currentCount == child.getCount()){ //Check if the count has not changed
                //If it hasn't
                child.kill();
                child.start();
            }
    
        }
    
    
        public static void main(String[] args){
            //Start up the parent function, it spawns the child
            new Parent();
        }
    
    }
    
    class Watchdog implements Runnable { //A timer that will run after five seconds
           private Thread t;
           private Parent parent;
           private int initialCount;
    
           public Watchdog(Parent parent, int count){ //make a  timer with a count, and access to the parent
               initialCount = count;
               this.parent = parent;
           }
    
           public void run() { //Timers logic
               try {
                   Thread.sleep(5000); // If you want to change the time requirement, modify it here
                   parent.restartChild(initialCount);
    
               } catch (InterruptedException e) {
                    System.out.println("Error in watchdog thread");
                }
    
           }
    
           public void start () // start the timer
           {
              if (t == null)
              {
                 t = new Thread (this);
                 t.start ();
              }
           }
    
        }
    
    public class Child implements Runnable{
    
        private Thread t;
        public int counter = 0;
        private boolean running;
    
        private Parent parent; // Record the parent function
    
        public Child(Parent parent){
            this.parent = parent;
        }
    
        private void initializeAll(){
            counter = 0;
            running = true;
        }
    
        public int getCount(){
            return counter;
        }
    
        @Override
        public void run() {
            while((counter <= 100)&&(running)){ 
                //The main logic for child
                counter +=1;
                System.out.println(counter);
                parent.report(counter); // Report a new count every two seconds
    
                try {
                    Thread.sleep(2000); // Wait two seconds
                } catch (InterruptedException e) {
                    System.out.println("Thread Failed");
                }
            }
    
        }
    
        public void start(){ //Start the thread
    
            initializeAll();
            t = new Thread(this);
            t.start();
    
        }
    
        public void kill(){ //Kill the thread
            running = false;
        }
    
    
    }