【问题标题】:synchronized notify, wait over property Boolean Object Java, IllegalMonitorStateException同步通知,等待属性 Boolean Object Java,IllegalMonitorStateException
【发布时间】:2019-12-23 18:24:26
【问题描述】:

我有这个代码。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class SyncProt0 {

  public static void main(String... args) {
    ExecutorService executorService = Executors.newCachedThreadPool();

    ProcessStep psWorker = new ProcessStep();
    ProcessStep psBoss = new ProcessStep();

    Worker worker = new Worker(executorService, psWorker, psBoss);
    Boss boss = new Boss(executorService, psBoss, psWorker);
  }

  public static class Worker implements Runnable {

    private final ProcessStep psWorker;
    private final ProcessStep psBoss;

    public Worker(ExecutorService executorService, ProcessStep psWorker, ProcessStep psBoss) {
      this.psWorker = psWorker;
      this.psBoss = psBoss;
      executorService.submit(this);
    }

    @Override
    public void run() {
      System.out.println("I'm -> Worker. I wait until Boss can see me!");
      while (!psBoss.isRunning()) {
        try {
          Thread.sleep(100);
        } catch (Exception e) { }
      }
      System.out.println("I'm -> Worker. Boss is seeing to me!");
      int counter = 0;
      while (counter < 6) {
        psWorker.setRunning(true);
        System.out.println("I'm Working ...");
        try {
          Thread.sleep(1000);
        } catch (Exception e) { }
        counter++;
      }
      psWorker.setRunning(false);
      psWorker.setFinished(true);
      System.out.println("I'm -> Worker. I left to work!");
    }

  }

  public static class Boss implements Runnable {
    private final ProcessStep psBoss;
    private final ProcessStep psWorker;
    private boolean running;

    public Boss(ExecutorService executorService, ProcessStep psBoss, ProcessStep psWorker) {
      this.psBoss = psBoss;
      this.psWorker = psWorker;

      executorService.submit(() -> {
        System.out.println("Boss. I have Runnable for turn of me when is needed");
        while (!this.psWorker.isFinished()) {
          try {
            Thread.sleep(100);
          } catch (InterruptedException e) { }
        }
        this.running = false;
      });
      executorService.submit(this);
    }

    @Override
    public void run() {
      System.out.println("I'm -> Boss. I'm delayed 4 Secs");
      try {
        Thread.sleep(4000);
      } catch (Exception e) { }

      System.out.println("I'm -> Boss. Let's go to check the work!");
      psBoss.setRunning(true);
      running = true;
      while (running) {
        System.out.println("I'm Checking ...");
        try {
          Thread.sleep(1000);
        } catch (Exception e) { }
      }
      psBoss.setRunning(false);
      psBoss.setFinished(true);
      System.out.println("I'm -> Boss The work end!");
    }

  }

  public static class ProcessStep {

    private final ReadWriteLock rwLock;
    private Boolean running;
    private Boolean finished;

    public ProcessStep() {
      this.rwLock = new ReentrantReadWriteLock();
      running = false;
      finished = false;
    }

    public Boolean isRunning() {
      Lock readLock = rwLock.readLock();
      readLock.lock();
      try {
        return running;
      } finally {
        readLock.unlock();
      }
    }

    public void setRunning(Boolean running) {
      Lock writeLock = rwLock.writeLock();
      writeLock.lock();
      try {
        this.running = running;
      } finally {
        writeLock.unlock();
      }
    }

    public Boolean isFinished() {
      Lock readLock = rwLock.readLock();
      readLock.lock();
      try {
        return finished;
      } finally {
        readLock.unlock();
      }
    }

    public void setFinished(Boolean finished) {
      Lock writeLock = rwLock.writeLock();
      writeLock.lock();
      try {
        this.finished = finished;
      } finally {
        writeLock.unlock();
      }
    }

  }

}

正确的输出是

I'm -> Worker. I wait until Boss can see me!
Boss. I have Runnable for turn of me when is needed
I'm -> Boss. I'm delayed 4 Secs
I'm -> Boss. Let's go to check the work!
I'm Checking ...
I'm -> Worker. Boss is seeing to me!
I'm Working ...
I'm Checking ...
I'm Working ...
I'm Checking ...
I'm Working ...
I'm Checking ...
I'm Working ...
I'm Checking ...
I'm Working ...
I'm Checking ...
I'm Working ...
I'm Checking ...
I'm -> Worker. I left to work!
I'm -> Boss The work end!

工作正常!

注意:我不想屏蔽所有 ProcessStep,只屏蔽一些按需属性!

我想在更改此代码的属性上使用WaitNotify 机制(在Boss 类中):

    while (!this.psWorker.isFinished()) {
      try {
        Thread.sleep(100);
      } catch (InterruptedException e) {
      }
    }

还有这段代码(在Worker 类中)

      while (!psBoss.isRunning()) {
        try {
          Thread.sleep(100);
        } catch (Exception e) {
        }
      }

当我使用此代码更改 WorkerBoss 类时:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class SyncProt1 {

  public static void main(String... args) {
    ExecutorService executorService = Executors.newCachedThreadPool();

    ProcessStep psWorker = new ProcessStep();
    ProcessStep psBoss = new ProcessStep();

    Worker worker = new Worker(executorService, psWorker, psBoss);
    Boss boss = new Boss(executorService, psBoss, psWorker);
  }

  public static class Worker implements Runnable {
    private final ProcessStep psWorker;
    private final ProcessStep psBoss;

    public Worker(ExecutorService executorService, ProcessStep psWorker, ProcessStep psBoss) {
      this.psWorker = psWorker;
      this.psBoss = psBoss;
      executorService.submit(this);

    }

    @Override
    public void run() {
      System.out.println("I'm -> Worker. I wait until Boss can see me!");
      synchronized (this.psBoss.isRunning()) {
        try {
          psBoss.isRunning().wait();
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
      System.out.println("I'm -> Worker. Boss is seeing to me!");
      int counter = 0;
      while (counter < 6) {
        synchronized (this.psWorker.isRunning()) {
          psWorker.setRunning(true);
          psWorker.isRunning().notify();
        }
        System.out.println("I'm Working ...");
        try {
          Thread.sleep(1000);
        } catch (Exception e) { }
        counter++;
      }
      synchronized (this.psWorker.isRunning()) {
        psWorker.setRunning(false);
        psWorker.isRunning().notify();
      }
      synchronized (this.psWorker.isFinished()) {
        psWorker.setFinished(true);
        psWorker.isFinished().notify();
      }
      System.out.println("I'm -> Worker. I left to work!");
    }

  }

  public static class Boss implements Runnable {
    private final ProcessStep psBoss;
    private final ProcessStep psWorker;
    private boolean running;

    public Boss(ExecutorService executorService, ProcessStep psBoss, ProcessStep psWorker) {
      this.psBoss = psBoss;
      this.psWorker = psWorker;

      executorService.submit(() -> {
        System.out.println("Boss. I have Runnable for turn of me when is needed");
        synchronized (this.psWorker.isFinished()) {
          try {
            psWorker.isFinished().wait();
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
        this.running = false;
      });
      executorService.submit(this);
    }

    @Override
    public void run() {
      System.out.println("I'm -> Boss. I'm delayed 4 Secs");
      try {
        Thread.sleep(4000);
      } catch (Exception e) { }

      System.out.println("I'm -> Boss. Let's go to check the work!");
      synchronized (this.psBoss.isRunning()) {
        psBoss.setRunning(true);
        psBoss.isRunning().notifyAll();
      }
      running = true;
      while (running) {
        System.out.println("I'm Checking ...");
        try {
          Thread.sleep(1000);
        } catch (Exception e) { }
      }
      synchronized (this.psBoss.isRunning()) {
        psBoss.setRunning(false);
        psBoss.isRunning().notify();
      }
      synchronized (this.psBoss.isFinished()) {
        psBoss.setFinished(true);
        psBoss.isFinished().notify();
      }
      System.out.println("I'm -> Boss The work end!");
    }

  }

  public static class ProcessStep {

    private final ReadWriteLock rwLock;
    private Boolean running;
    private Boolean finished;

    public ProcessStep() {
      this.rwLock = new ReentrantReadWriteLock();
      running = false;
      finished = false;
    }

    public Boolean isRunning() {
      Lock readLock = rwLock.readLock();
      readLock.lock();
      try {
        return running;
      } finally {
        readLock.unlock();
      }
    }

    public void setRunning(Boolean running) {
      Lock writeLock = rwLock.writeLock();
      writeLock.lock();
      try {
        this.running = running;
      } finally {
        writeLock.unlock();
      }
    }

    public Boolean isFinished() {
      Lock readLock = rwLock.readLock();
      readLock.lock();
      try {
        return finished;
      } finally {
        readLock.unlock();
      }
    }

    public void setFinished(Boolean finished) {
      Lock writeLock = rwLock.writeLock();
      writeLock.lock();
      try {
        this.finished = finished;
      } finally {
        writeLock.unlock();
      }
    }

  }

}

输出是

I'm -> Worker. I wait until Boss can see me!
Boss. I have Runnable for turn of me when is needed
I'm -> Boss. I'm delayed 4 Secs
I'm -> Boss. Let's go to check the work!

Worker 还在等待!

是否可以使用 synchronized OVER 属性?

另一个结果相同的版本是:

  public static class Worker implements Runnable {
    private final ProcessStep psWorker;
    private final ProcessStep psBoss;

    public Worker(ExecutorService executorService, ProcessStep psWorker, ProcessStep psBoss) {
      this.psWorker = psWorker;
      this.psBoss = psBoss;
      executorService.submit(this);

    }

    @Override
    public void run() {
      System.out.println("I'm -> Worker. I wait until Boss can see me!");
      synchronized (psBoss) {
        try {
          psBoss.isRunning().wait();
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
      System.out.println("I'm -> Worker. Boss is seeing to me!");
      int counter = 0;
      while (counter < 6) {
        synchronized (psWorker) {
          psWorker.setRunning(true);
          psWorker.isRunning().notify();
        }
        System.out.println("I'm Working ...");
        try {
          Thread.sleep(1000);
        } catch (Exception e) { }
        counter++;
      }
      synchronized (psWorker) {
        psWorker.setRunning(false);
        psWorker.isRunning().notify();
      }
      synchronized (psWorker) {
        psWorker.setFinished(true);
        psWorker.isFinished().notify();
      }
      System.out.println("I'm -> Worker. I left to work!");
    }

  }

  public static class Boss implements Runnable {
    private final ProcessStep psBoss;
    private final ProcessStep psWorker;
    private boolean running;

    public Boss(ExecutorService executorService, ProcessStep psBoss, ProcessStep psWorker) {
      this.psBoss = psBoss;
      this.psWorker = psWorker;

      executorService.submit(() -> {
        System.out.println("Boss. I have Runnable for turn of me when is needed");
        synchronized (psWorker) {
          try {
            psWorker.isFinished().wait();
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
        this.running = false;
      });
      executorService.submit(this);
    }

    @Override
    public void run() {
      System.out.println("I'm -> Boss. I'm delayed 4 Secs");
      try {
        Thread.sleep(4000);
      } catch (Exception e) { }

      System.out.println("I'm -> Boss. Let's go to check the work!");
      synchronized (psBoss) {
        psBoss.setRunning(true);
        psBoss.isRunning().notifyAll();
      }
      running = true;
      while (running) {
        System.out.println("I'm Checking ...");
        try {
          Thread.sleep(1000);
        } catch (Exception e) { }
      }
      synchronized (psBoss) {
        psBoss.setRunning(false);
        psBoss.isRunning().notify();
      }
      synchronized (psBoss) {
        psBoss.setFinished(true);
        psBoss.isFinished().notify();
      }
      System.out.println("I'm -> Boss The work end!");
    }

  }

【问题讨论】:

  • 你能缩小范围吗?这是很多代码
  • 随着更改删除 List&lt;Future&lt;?&gt;&gt; futureList = new ArrayList&lt;&gt;();this.futureList.add(this.executorService.submit(this)); 更改为 executorService.submit(this); IllegalMonitorStateException 没有出现,可能有些错误。
  • 还有很多代码,你确实意识到了,对吧?
  • @Eugene 不幸的是,要删除的代码将是 System.out.println(...) 但如何检查状态?你会删除什么代码?
  • 不,不可能“对属性使用同步”。 synchronized 语句适用于 objects,因此当您使用 synchronized (this.psBoss.isRunning()) 时,您正在同步 current value,它正在发生变化。由于属性不是对象,因此您无法对其进行同步。您可以创建一个专用于该属性的对象以对其进行同步。或者你使用this.psBoss。使同步工作重要的是,对于所有操作,它必须是同一个对象。当然,您调用的对象 waitnotify 也必须是同一个对象。

标签: java-8 wait synchronized notify


【解决方案1】:

我想,我明白了!

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class SyncProt1 {

  public static void main(String... args) {
    List<Future<?>> futureList = new ArrayList<>();
    ExecutorService executorService = Executors.newCachedThreadPool();
    ProcessStep psWorker = new ProcessStep();
    ProcessStep psBoss = new ProcessStep();

    Worker worker = new Worker(futureList, executorService, psWorker, psBoss);
    Boss boss = new Boss(futureList, executorService, psBoss, psWorker);
  }

  public static class Worker implements Runnable {

    private final ProcessStep psWorker;
    private final ProcessStep psBoss;

    public Worker(List<Future<?>> futureList, ExecutorService executorService, ProcessStep psWorker, ProcessStep psBoss) {
      this.psWorker = psWorker;
      this.psBoss = psBoss;
      futureList.add(executorService.submit(this));
    }

    @Override
    public void run() {
      System.out.println("I'm -> Worker. I wait until Boss can see me!");
      synchronized (this.psBoss.getRunning()) {
        try {
          this.psBoss.getRunning().wait();
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
      System.out.println("I'm -> Worker. Boss is seeing to me!");
      int counter = 0;
      while (counter < 6) {
        synchronized (this.psWorker.getRunning()) {
          this.psWorker.getRunning().setStep(Boolean.TRUE);
          psWorker.getRunning().notify();
        }
        System.out.println("I'm Working ...");
        try {
          Thread.sleep(1000);
        } catch (Exception e) {
        }
        counter++;
      }
      synchronized (this.psWorker.getRunning()) {
        this.psWorker.getRunning().setStep(Boolean.FALSE);
        this.psWorker.getRunning().notify();
      }
      synchronized (this.psWorker.getFinished()) {
        this.psWorker.getFinished().setStep(Boolean.TRUE);
        this.psWorker.getFinished().notify();
      }
      System.out.println("I'm -> Worker. I left to work!");
    }

  }

  public static class Boss implements Runnable {

    private final ProcessStep psBoss;
    private final ProcessStep psWorker;
    private boolean running;

    public Boss(List<Future<?>> futureList, ExecutorService executorService, ProcessStep psBoss, ProcessStep psWorker) {
      this.psBoss = psBoss;
      this.psWorker = psWorker;

      futureList.add(executorService.submit(() -> {
        System.out.println("Boss. I have Runnable for turn of me when is needed");
        synchronized (this.psWorker.getFinished()) {
          try {
            this.psWorker.getFinished().wait();
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
        System.out.println("Boss. The worker Finished!");
        this.running = false;
      }));
      futureList.add(executorService.submit(this));
    }

    @Override
    public void run() {
      System.out.println("I'm -> Boss. I'm delayed 4 Secs. " + new Date());
      try {
        Thread.sleep(4000);
      } catch (Exception e) {
      }

      System.out.println("I'm -> Boss. Let's go to check the work at " + new Date());
      synchronized (this.psBoss.getRunning()) {
        this.psBoss.getRunning().setStep(Boolean.TRUE);
        this.psBoss.getRunning().notify();
      }
      running = true;
      while (running) {
        System.out.println("I'm Checking ...");
        try {
          Thread.sleep(1000);
        } catch (Exception e) {
        }
      }
      synchronized (this.psBoss.getRunning()) {
        this.psBoss.getRunning().setStep(Boolean.FALSE);
        this.psBoss.getRunning().notify();
      }
      synchronized (this.psBoss.getFinished()) {
        this.psBoss.getFinished().setStep(Boolean.TRUE);
        this.psBoss.getFinished().notify();
      }
      System.out.println("I'm -> Boss The work end!");
    }

  }

  public static class ProcessStep {

    private final Step created = new Step();
    private final Step running = new Step();
    private final Step finished = new Step();

    public Step getCreated() {
      return created;
    }

    public Step getRunning() {
      return running;
    }

    public Step getFinished() {
      return finished;
    }

  }

  public static class Step {

    private final ReadWriteLock rwLock;
    private Boolean step;

    public Step() {
      this.rwLock = new ReentrantReadWriteLock();
      step = false;
    }

    public Boolean getStep() {
      Lock readLock = rwLock.readLock();
      readLock.lock();
      try {
        return step;
      } finally {
        readLock.unlock();
      }
    }

    public void setStep(Boolean step) {
      Lock writeLock = rwLock.writeLock();
      writeLock.lock();
      try {
        this.step = step;
      } finally {
        writeLock.unlock();
      }
    }

  }

}

输出

I'm -> Worker. I wait until Boss can see me!
Boss. I have Runnable for turn of me when is needed
I'm -> Boss. I'm delayed 4 Secs. Mon Aug 19 20:30:44 COT 2019
I'm -> Boss. Let's go to check the work at Mon Aug 19 20:30:48 COT 2019
I'm Checking ...
I'm -> Worker. Boss is seeing to me!
I'm Working ...
I'm Checking ...
I'm Working ...
I'm Checking ...
I'm Working ...
I'm Working ...
I'm Checking ...
I'm Checking ...
I'm Working ...
I'm Checking ...
I'm Working ...
I'm Checking ...
I'm -> Worker. I left to work!
Boss. The worker Finished!
I'm -> Boss The work end!

编辑删除LockReadWriteLockReentrantReadWriteLock。执行同步和编辑getStepsetStep 方法。

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class SyncProt4 {

  public static void main(String... args) {
    List<Future<?>> futureList = new ArrayList<>();
    ExecutorService executorService = Executors.newCachedThreadPool();
    ProcessStep psWorker = new ProcessStep();
    ProcessStep psBoss = new ProcessStep();

    Worker worker = new Worker(futureList, executorService, psWorker, psBoss);
    Boss boss = new Boss(futureList, executorService, psBoss, psWorker);

  }

  public static class Worker implements Runnable {

    private final ProcessStep psWorker;
    private final ProcessStep psBoss;

    public Worker(List<Future<?>> futureList, ExecutorService executorService, ProcessStep psWorker, ProcessStep psBoss) {
      this.psWorker = psWorker;
      this.psBoss = psBoss;
      futureList.add(executorService.submit(this));
    }

    @Override
    public void run() {
      System.out.println("I'm Worker -> I wait until Boss can see me!");
      while (!this.psBoss.getRunning().getStep());

      System.out.println("I'm Worker -> Boss is seeing to me!");
      int counter = 0;
      while (counter < 6) {
        this.psWorker.getRunning().setStep(Boolean.TRUE);
        System.out.println("I'm Worker -> I'm Working ...");
        try {
          Thread.sleep(1000);
        } catch (Exception e) {
        }
        counter++;
      }
      this.psWorker.getRunning().setStep(Boolean.FALSE);
      this.psWorker.getFinished().setStep(Boolean.TRUE);
      System.out.println("I'm Worker -> I left to work!");
    }

  }

  public static class Boss implements Runnable {

    private final ProcessStep psBoss;
    private final ProcessStep psWorker;
    private boolean running;

    public Boss(List<Future<?>> futureList, ExecutorService executorService, ProcessStep psBoss, ProcessStep psWorker) {
      this.psBoss = psBoss;
      this.psWorker = psWorker;

      futureList.add(executorService.submit(() -> {
        System.out.println("I'm Boss -> I have Runnable for turn of me when is needed");
        while (!this.psWorker.getFinished().getStep());
        System.out.println("I'm Boss -> The Worker Finished!");
        this.running = false;
      }));
      futureList.add(executorService.submit(this));
    }

    @Override
    public void run() {
      System.out.println("I'm Boss -> I'm delayed 4 Secs. " + new Date());
      try {
        Thread.sleep(4000);
      } catch (Exception e) {
      }

      System.out.println("I'm Boss -> Let's go to check the work at " + new Date());
      this.psBoss.getRunning().setStep(Boolean.TRUE);
      running = true;
      while (running) {
        System.out.println("I'm Boss -> I'm Checking ...");
        try {
          Thread.sleep(1000);
        } catch (Exception e) {
        }
      }
      this.psBoss.getRunning().setStep(Boolean.FALSE);
      this.psBoss.getFinished().setStep(Boolean.TRUE);
      System.out.println("I'm Boss -> The work ends!");
    }

  }

  public static class ProcessStep {

    private final Step created = new Step();
    private final Step running = new Step();
    private final Step finished = new Step();

    public Step getCreated() {
      return created;
    }

    public Step getRunning() {
      return running;
    }

    public Step getFinished() {
      return finished;
    }

  }

  public static class Step {

    private Boolean step;

    public Step() {
      step = false;
    }

    public synchronized Boolean getStep() {
      try {
        wait();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      return step;
    }

    public synchronized void setStep(Boolean step) {
      this.step = step;
      notifyAll();
    }

  }

}

新的输出

I'm Worker -> I wait until Boss can see me!
I'm Boss -> I have Runnable for turn of me when is needed
I'm Boss -> I'm delayed 4 Secs. Tue Aug 20 21:27:26 COT 2019
I'm Boss -> Let's go to check the work at Tue Aug 20 21:27:30 COT 2019
I'm Boss -> I'm Checking ...
I'm Worker -> Boss is seeing to me!
I'm Worker -> I'm Working ...
I'm Boss -> I'm Checking ...
I'm Worker -> I'm Working ...
I'm Boss -> I'm Checking ...
I'm Worker -> I'm Working ...
I'm Boss -> I'm Checking ...
I'm Worker -> I'm Working ...
I'm Boss -> I'm Checking ...
I'm Worker -> I'm Working ...
I'm Boss -> I'm Checking ...
I'm Worker -> I'm Working ...
I'm Worker -> I left to work!
I'm Boss -> The Worker Finished!
I'm Boss -> I'm Checking ...
I'm Boss -> The work ends!

【讨论】:

  • @Holger 我理解错误,谢谢,我得到了解决方案。
  • 在您的代码中,同步Step 对象并调用其setStep 方法,然后调用notify() 的逻辑已重复五次。考虑将其逻辑移入Step 类如何简化代码。只需将Step.setStep 设为synchronized 方法,该方法最后调用notifyAll()。然后,向它添加一个waitForTrue() 方法,也就是synchronized,其中包含简单的while(!step) wait(); 逻辑,并且使用不同步骤的所有代码都变得更加简单。然后,当你也将getStep() 设为synchronized 方法时,你可以去掉多余的ReadWriteLock
猜你喜欢
  • 2011-10-30
  • 1970-01-01
  • 1970-01-01
  • 2015-01-26
  • 1970-01-01
  • 2017-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多