简体   繁体   中英

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.

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. 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. 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. :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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