代码意外停止,而不是无限运行

时间:2019-07-19 13:33:41

标签: java

这是一个经典的排队问题。应该放一个数字并得到相同的数字。这应该永远持续下去。

我的老师使用此问题来演示wait()的用法。 但是我的处理方式有所不同。

this.valService.checkVal(email,pwd).subscribe((data : any)=>{
  },
  (err : HttpErrorResponse)=>{
    this.isLoginError = true;
  });

然后,主要是将同一个Q对象链接到消费者和生产者。 然后,我启动了两个线程(消费者对象和生产者对象)。

代码在一些数字(例如48,84等)之后停止。 但我认为这应该是一个无限循环。

1 个答案:

答案 0 :(得分:0)

您的代码中存在多个问题。

首先,即使是getter和setter也不是线程安全的。 在生产者的run()中for循环的主体中

if(q.isReady())
            {
                q.get();
                q.setReady(false);
            }
...

q.isReady()和if的正文可能不会在一行之后执行。

  • 一个问题可能是q.isReady()对第一个线程返回true,然后第二个线程获取了句柄,还在执行q.isReady(),因此if-> q.setReqady的主体(false)被执行。
  • 第一个线程获取到句柄,还执行了意外的q.get()和q.setReady(false)(因为线程返回了之前的位置)。

有两种方法可以解决此问题:

1。同步获取器和设置器

public synchronized void setReady(boolean ready) {
        Ready = ready;
    }
    public synchronized boolean isReady() {
        return Ready;
    }

2。同步需要“原子”执行的部分

  • 此方法更容易出错,因为您必须从外部同步使用这些方法。执行相同方法的地方可能不止一个-您必须在所有地方同步它们。 您可以通过将方法链放在“ synchronized(关键对象){...}”块中来实现此目的。“对象的实例”对所有线程都是锁定的,直到完全执行了同步的主体为止。

3。您执行线程错误

  1. 因为您没有显示主要方法,所以我不得不想象您是如何做到的。 我的建议是您启动多个消费者和生产者,这将导致同步错误。

如果您只启动一个生产者和一个消费者...

  1. 您错误地启动了线程 如果您的主要方法只是这样:

    ...
    Consumer1.start(); producer1.start(); }

这里的问题是您不必等待线程完成。即使线程应该继续运行,您的主线程也会在启动其他线程后停止执行。 JVM将在某些时候清理丢失的线程(当您丢失对它们的参照时,它们将不会永远运行)。

只需调用Consumer1.join()或procer1.join()(或两者)即可对其进行修复。