【问题标题】:Java I need to get a variable from a different running class as that class update the vairableJava 我需要从不同的运行类获取一个变量,因为该类更新 vairable
【发布时间】:2022-12-09 02:05:11
【问题描述】:

我正在寻找一种方法来从另一个正在运行的类中获取变量的值,因为该类正在更新变量

我基本上是尝试分块复制文件,但是如何更新不同 java 类的进度

所以基本上:

类复制文件变量复制数据 --> 检查进度类变量显示进度

我是 java 的新手,所以我已经犯了很多错误

public class Class_one
{

    public static void main(String[] args) throws InterruptedException {
        Class_three class_three = new Class_three();
        while(true) {
            Class_one class_one = new Class_one();
            long test = class_three.data();
            System.out.println(test);
        }

    }
}
public class Class_two {
    public static void main(String[] args) throws InterruptedException {
        Class_three class_three = new Class_three();
        class_three.generatea();
    }
}

public class Class_three {
    public static long a ;
    public long c ;
    public void generatea() throws InterruptedException {
        for (long b = 0 ; b < 100000000000L; b++){

            Thread.sleep(1000);
            a = b;
            System.out.println("generatea : " + a);


            //this.c++;
        }

    }
    public  long data() throws InterruptedException {

         long b = a;
        System.out.print("a : " + "\tb : " + b);
        return b;
    }

}

所以 Class_one 需要能够获得全局 a 的 Class_three 值,但 Class_two 正在运行 Class_Three

希望这是有道理的

【问题讨论】:

    标签: java


    【解决方案1】:

    从您的描述中可以清楚地看出您不确定谁控制进度。 肯定有几种方法可以解决您的问题。 假设您的类名为 Copy 和 Observer。

    方法一: 复制控件并在构造函数中接收 Observer 的实例。 Copy 有一个复制循环,在每次迭代后调用 Observer 中的一个方法。 然后可以将进度传递给 Observer 中的方法。

    例子:

    // a test class with your main method
    public class Test {
        public static void main(String[] args) {
            Observer observer = new Observer();
            Copy copy = new Copy(1000, observer);
            copy.start();
        }
    }
    
    
    // the oberver class
    public class Observer {
        public void progress(int current, int blocks) {
            System.out.println(current + "/" + blocks);
        }
    }
    
    
    // the copy class
    public class Copy {
        public final int blocks;
        private Observer observer;
    
        public Copy(int blocks, Observer observer) {
            this.blocks = blocks;
            this.observer = observer;
        }
    
        public void start() {
            for(int current = 1; current <= blocks; current++) {
                observer.progress(current, blocks);
            }
        }
    }
    

    方法二: Observer 在构造函数中控制并接收 Copy 的实例。 Observer 有一个循环,在每次迭代中调用 Copy 中的方法,只要结果返回 True 即可。 例如,然后可以从变量中读取进度。

    例子:

    // a test class with your main method
    public class Test {
        public static void main(String[] args) {
            Copy copy = new Copy(1000);
            Observer observer = new Observer(copy);
            observer.start();
        }
    }
    
    
    // the oberver class
    public class Observer {
        private Copy copy;
    
        public Observer(Copy copy) {
            this.copy = copy;
        }
    
        public void start() {
            while (copy.next()) {
                System.out.println(copy.getCurrent() + "/" + copy.blocks);
            }
        }
    }
    
    
    // the copy class
    public class Copy {
        public final int blocks;
        private int current = 1;
    
        public Copy(int blocks) {
            this.blocks = blocks;
        }
    
        public boolean next() {
            current++;
            return current <= blocks;
        }
    
        public int getCurrent() {
            return current;
        }
    }
    

    方法三: Observer 在自己的线程中运行,并在构造函数中获取 Copy 的实例。 Copy 有一个复制循环,并在每次迭代后用进度更新一个变量。 Observer 有一个观察者循环,并在每次传递时从 Copy 中的变量中读取进度。当进度完成时,观察者结束其循环。

    在撰写本文时,已经存在基于线程的答案。

    【讨论】:

      【解决方案2】:

      线程呢?

      class Test {
          public static void main(String[] args) {
              Class_three class_three = new Class_three();
              new Thread(() -> {
                  while (true) {
                      long test = 0;
                      try {
                          test = class_three.data();
                      } catch (InterruptedException e) {
                          throw new RuntimeException(e);
                      }
                      System.out.println(test);
                  }
              }).start();
      
              new Thread(() -> {
                  try {
                      class_three.generatea();
                  } catch (InterruptedException e) {
                      throw new RuntimeException(e);
                  }
              }).start();
          }
      }
      

      【讨论】:

        【解决方案3】:

        您的代码似乎导致了这样的解决方案:

        (请注意,这与您编写的程序不完全相同。)

        该解决方案有几个缺点:

        • 您需要两个独立的线程,因为这两个循环应该是独立的。
        • 存储需要是线程安全的,因为它由两个线程访问。
        • 不清楚何时创建存储,因为它必须可以从两个独立的类访问。

        作为存储,您确实使用了 ClassThree 的静态变量。我不会这样做。静态变量就像全局变量,我认为应尽可能避免使用全局变量是常识。

        所以我会寻求另一种解决方案:

        在此解决方案中,ClassOne 知道 ClassTwo。 ClassOne 观察 ClassTwo,ClassTwo 观察 ClassThree。

        这个解决方案有一个有趣的选项,让 ClassOne 不仅可以观察进度,还可以终止整个复制过程,例如通过在回调方法中使用一些返回值。

        一个非常简单的回调看起来像这样:

        public interface ProgressIndicator {
            Boolean progress(long a);
        }
        

        这可以像这样在 ClassThree 中使用:

        public class ClassThree {
        
            private long a ;
        
            public void generatea(ProgressIndicator indicator) throws InterruptedException {
                for (long b = 0 ; b < 100000000000L; b++){
                    Thread.sleep(1000);
                    a = b;
                    if(!indicator.progress(a)){
                        break;
                    };
                }
            }
        
            public  long data() {
                return a;
            }
        
            public static void main(String[] args) throws InterruptedException {
                var copyTask = new ClassThree();
                copyTask.generatea(new ProgressIndicator() {
                    @Override
                    public Boolean progress(long a) {
                        System.out.println("Progress: " + a);
                        return a < 10;
                    }
                });
            }
        }
        

        输出将是:

        Progress: 0
        Progress: 1
        Progress: 2
        Progress: 3
        Progress: 4
        Progress: 5
        Progress: 6
        Progress: 7
        Progress: 8
        Progress: 9
        Progress: 10
        

        因此,通过在 ProgressIndicator 中返回 false,我们停止了复制过程。

        我没有使用第一类和第二类,因为我只在主要方法中创建了所有必要的类以保持简单。

        您会注意到这与answer of QuinncyJones 中的方法 1 非常相似。你是对的:除了不使用构造函数来获取 ProgressIndicator 之外,没有概念上的差异。我只是想让这个解决方案在方法 2 和 3 中脱颖而出,并解释为什么我认为这是最好的解决方案。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-07-12
          • 2019-05-02
          • 1970-01-01
          • 2014-02-03
          相关资源
          最近更新 更多