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

在多个java线程之间共享对象,java,multithreading,Java,Multithreading,我希望能够同时运行两个依赖于同一全局变量的方法。第一个方法定期更新共享变量,但从未完成运行。第二种方法跟踪时间。当时间用完时,第二个方法返回第一个方法中共享变量的最后一个结果。下面是我到目前为止所做的,在我需要帮助的地方注释掉了psedoocode package learning; public class testmath{ public static void main(String[] args){ long finishBy = 10000;

我希望能够同时运行两个依赖于同一全局变量的方法。第一个方法定期更新共享变量,但从未完成运行。第二种方法跟踪时间。当时间用完时,第二个方法返回第一个方法中共享变量的最后一个结果。下面是我到目前为止所做的,在我需要帮助的地方注释掉了psedoocode

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;

    }

}
包学习;
公共课数学测验{
公共静态void main(字符串[]args){
长finishBy=10000;
int currentresult=0;
/*
*以单独的螺纹/平行方式运行eversquare(0)
*/
int finalresult=经理(finishBy);
系统输出打印LN(最终结果);
}
公共静态整数平方(整数x){
返回x*x;
}
公共静态无效eversquare(int x){
int-newresult;
而(2==2){
x+=1;
新结果=平方(x);
/*
*将newresult存储为名为currentresult的全局
*/
}
}
公共静态int管理器(长finishBy){
而(System.currentTimeMillis()+1000
您只需运行一个附加线程:

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;
  }
}
公共类主{
/**
*延迟毫秒,直到完成。
*/
专用静态最终长饰面_=10000;
/**
*从这个号码开始。
*/
专用静态最终int START_=1;
/**
*eversquare过程之间的延迟(毫秒)。
*/
两次通过之间的专用静态最终长延迟=50;
/**
*保存当前结果。“volatile”关键字告诉JVM
*值可能被另一个线程更改,因此不要缓存它。标记
*变量作为volatile会导致“严重”的性能损失,所以不要使用它
*除非真的有必要。
*/
私有静态volatile int currentResult=0;
公共静态void main(字符串[]args){
//创建一个线程并行运行“eversquare”
Thread eversquareThread=新线程(new Runnable(){
@重写公共无效运行(){
eversquare(以开始,在两次通行之间延迟);
}
});
//使eversquare线程在“main”方法退出时关闭
//(否则程序将永远无法完成,因为“eversquare”线程
//由于其“while”循环,将永远运行)
setDaemon(true);
//启动eversquare线程
eversquareThread.start();
//等待指定的延迟结束
长currentTime=System.currentTimeMillis();
最终长停止时间=当前时间+结束时间;
while(当前时间<停止时间){
最终长睡眠时间=停止时间-当前时间;
试一试{
睡眠(睡眠时间);
}捕获(中断异常例外){
//在不太可能发生中断异常的情况下,请不要执行任何操作
//“while”循环将继续,直到完成为止
}
currentTime=System.currentTimeMillis();
}
系统输出打印项次(currentResult);
}
/**
*增加值并计算其平方。如果保留它自己的值,则永远运行
*设备。
*
*@param startValue
*要开始的值。
*
*@param延迟
*如果您尝试在两次传递之间毫不延迟地运行此程序,它将
*最大化CPU并耗尽所有其他线程。此值是等待时间
*在通行证之间。
*/
专用静态无效eversquare(最终整数起始值,最终长延迟){
int currentValue=起始值;
while(true){//永远运行(只需使用“true”;“2==2”看起来很傻)
currentResult=square(currentValue);//存储在全局“currentResult”中
currentValue++;//甚至比“x+=1”还要短
如果(延迟>0){
请尝试{//需要处理“Thread.sleep()”可能引发的异常
睡眠(延迟);
}catch(InterruptedException ex){/“Thread.sleep()”可以抛出此
//在不太可能发生的情况下,只需打印到控制台即可
//InterruptedException--一切都会好起来的
例如printStackTrace();
}
}
}
}
专用静态整数平方(整数x){
返回x*x;
}
}
我还应该提到,“volatile”关键字适用于(大多数)原语,因为您现在看到的任何JVM都保证它们将被原子化修改。对象并非如此,您需要使用同步块和锁来确保它们始终处于一致状态


大多数人还会提到,您确实应该不要在方法本身上使用
synchronized
关键字,而是在特定的“lock”对象上进行同步。通常,这个锁对象不应该在代码外部可见。这有助于防止人们错误地使用您的代码,使自己陷入麻烦,然后试图责怪您。:)

为什么
while(2==2)
而不是
while(true)
?请记住,您可以在一个方法中同步一个块,而不仅仅是整个方法。请阅读并发教程,并尝试以下操作:@PatriciaShanahan它们具有等效的布尔值,将来将使用true。在三天前开始学习java,你能解释一下你的意思是“你可以同步一个方法中的一个块,而不仅仅是一个完整的方法”,它将如何帮助我。你可能希望考虑使用AtomicInteger来共享这个值。这是非常有帮助的。我唯一不清楚的是为什么要推迟。我的理解是,添加多个线程允许程序使用计算机的多个CPU。当我阅读你的代码时,它每次关闭函数50毫秒,浪费了宝贵的计算时间