简体   繁体   English

在多个线程之间共享对象Java

[英]Sharing an object between multiple threads java

I would like to be able to run two methods at the same time that rely on the same global variable. 我希望能够同时运行依赖同一全局变量的两个方法。 The first method periodically updates the shared variable, but never finishes running. 第一种方法会定期更新共享变量,但永远不会完成运行。 The second method keeps track of time. 第二种方法跟踪时间。 When time runs out, the second method returns the last result of the shared variable from the first method. 当时间用完时,第二种方法从第一种方法返回共享变量的最后结果。 Below is what I have so far, with commented out pseduocode in the places where I need help. 以下是我到目前为止的内容,并在需要帮助的地方注释了pseduocode。

package learning;

public class testmath{
    public static void main(String[] args){

        long finishBy = 10000;
        int currentresult = 0;

        /*
         * run eversquare(0) in  a seperate thread /in parallel
         */


        int finalresult = manager(finishBy);
        System.out.println(finalresult);
    }


    public static int square(int x){
        return x * x;
    }

    public static void eversquare(int x){
        int newresult;
        while(2 == 2){
            x += 1;
            newresult = square(x);
            /*
             * Store newresult as a global called currentresult
             */

        }
    }



    public static int manager(long finishBy){


        while(System.currentTimeMillis() + 1000 < finishBy){
            Thread.sleep(100);
        }

        /*
         * Access global called currentresult and create a local called currentresult
         */     
        return currentresult;

    }

}

You only need to run one additional thread: 您只需要运行一个附加线程:

public class Main {
  /**
   * Delay in milliseconds until finished.
   */
  private static final long FINISH_BY = 10000;
  /**
   * Start with this number.
   */
  private static final int START_WITH = 1;
  /**
   * Delay between eversquare passes in milliseconds.
   */
  private static final long DELAY_BETWEEN_PASSES = 50;
  /**
   * Holds the current result. The "volatile" keyword tells the JVM that the
   * value could be changed by another thread, so don't cache it. Marking a
   * variable as volatile incurs a *serious* performance hit so don't use it
   * unless really necessary.
   */
  private static volatile int currentResult = 0;

  public static void main(String[] args) {
    // create a Thread to run "eversquare" in parallel
    Thread eversquareThread = new Thread(new Runnable() {
      @Override public void run() {
        eversquare(START_WITH, DELAY_BETWEEN_PASSES);
      }
    });

    // make the eversquare thread shut down when the "main" method exits
    // (otherwise the program would never finish, since the "eversquare" thread
    // would run forever due to its "while" loop)
    eversquareThread.setDaemon(true);

    // start the eversquare thread
    eversquareThread.start();

    // wait until the specified delay is up
    long currentTime = System.currentTimeMillis();
    final long stopTime = currentTime + FINISH_BY;
    while (currentTime < stopTime) {
      final long sleepTime = stopTime - currentTime;
      try {
        Thread.sleep(sleepTime);
      } catch (InterruptedException ex) {
        // in the unlikely event of an InterruptedException, do nothing since
        // the "while" loop will continue until done anyway
      }
      currentTime = System.currentTimeMillis();
    }
    System.out.println(currentResult);
  }

  /**
   * Increment the value and compute its square. Runs forever if left to its own
   * devices.
   *
   * @param startValue
   * The value to start with.
   *
   * @param delay
   * If you were to try to run this without any delay between passes, it would
   * max out the CPU and starve any other threads. This value is the wait time
   * between passes.
   */
  private static void eversquare(final int startValue, final long delay) {
    int currentValue = startValue;
    while (true) { // run forever (just use "true"; "2==2" looks silly)
      currentResult = square(currentValue); // store in the global "currentResult"
      currentValue++; // even shorter than "x += 1"
      if (delay > 0) {
        try { // need to handle the exception that "Thread.sleep()" can throw
          Thread.sleep(delay);
        } catch (InterruptedException ex) { // "Thread.sleep()" can throw this
          // just print to the console in the unlikely event of an
          // InterruptedException--things will continue fine
          ex.printStackTrace();
        }
      }
    }
  }

  private static int square(int x) {
    return x * x;
  }
}

I should also mention that the "volatile" keyword works for (most) primitives, since any JVM you'll see these days guarantees they will be modified atomically. 我还应该提到,“ volatile”关键字适用于(大多数)原语,因为您现在看到的所有JVM都可以保证对它们进行原子修改。 This is not the case for objects, and you will need to use synchronized blocks and locks to ensure they are always "seen" in a consistent state. 对象不是这种情况,您将需要使用同步的块和锁来确保始终以一致的状态“看到”它们。

Most people will also mention that you really should not use the synchronized keyword on the method itself, and instead synchronize on a specific "lock" object. 大多数人还会提到,你真的应该使用synchronized的方法本身的关键字,并在特定的“锁”的对象,而不是同步。 And generally this lock object should not be visible outside your code. 通常,此锁对象在代码外部不应该可见。 This helps prevent people from using your code incorrectly, getting themselves into trouble, and then trying to blame you. 这有助于防止人们错误地使用您的代码,使自己陷入困境,然后试图怪罪您。 :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM