如何从thread1等待直到thread2通知

时间:2012-09-25 16:08:57

标签: java multithreading concurrency

我是多线程的新手,在阅读多线程时,想到编写这个花哨的多线程代码来执行以下操作。

我的反击类如下。

class Counter {
  private int c = 0;

  public void increment() {
    System.out.println("increment value: "+c);
      c++;
  }

  public void decrement() {
      c--;
      System.out.println("decrement value: "+c);
  }

  public int value() {
      return c;
  }

}

此Counter对象在两个线程之间共享。 一旦线程启动,我需要执行以下操作。 我希望Thread2等到Thread1将Counter对象的计数递增1。 完成此操作后,然后线程1通知thread2,然后Thread1开始等待thread2将值递减1。 然后thread2启动并递减值1并再次通知thread1,然后thread2开始等待thread1。重复这个过程几次。

我怎样才能做到这一点。非常感谢提前。

我做了以下事情。

public class ConcurrencyExample {

  private static Counter counter;
  private static DecrementCount t1;
  private static IncrementCount t2;

  public static void main(String[] args) {
    Counter counter = new Counter();
    Thread t1 = new Thread(new IncrementCount(counter));
    t1.start();

    Thread t2 = new Thread(new DecrementCount(counter));
    t2.start();

  }

}


public class DecrementCount implements Runnable {

  private static Counter counter;

  public DecrementCount(Counter counter) {
    this.counter = counter;
  }

  @Override
  public void run() {
    for (int i = 0; i < 1000; i++) {
      counter.decrement();     
      System.out.println("decreamented");
    }
  }

}


public class IncrementCount implements Runnable {

  private static Counter counter;

  public IncrementCount(Counter counter) {
    this.counter = counter;
  }

  @Override
  public void run() {
    for (int i = 0; i < 1000; i++) {
      counter.increment();
      System.out.println("Incremented");
    }

  }

}

4 个答案:

答案 0 :(得分:3)

结帐Semaphore。您需要两个,每个线程一个:incSemaphoredecSemaphore。在DecrementCount执行:

for (int i = 0; i < 1000; i++) {
  decSemaphore.acquire();
  counter.decrement();     
  System.out.println("decreamented");
  incSemaphore.release();
}

对称地实施IncrementCount。对于incSemaphore1的初始值应为0decSemaphore

BTW您的Counter也需要同步(请参阅synchronized关键字和AtomicInteger)。

答案 1 :(得分:0)

Condition与布尔标志一起使用。

final Lock lock = new ReentrantLock();
final Condition incremented= lock.newCondition(); 
final Condition decremented= lock.newCondition(); 

将您的计数器更改为

说明:

我们使用了两个条件,一个递增,一个递减。基于布尔标志,我们检查是否必须等待一个条件。

 class Counter {
private int c = 0;
boolean increment = false;

final Lock lock = new ReentrantLock();
final Condition incremented = lock.newCondition();
final Condition decremented = lock.newCondition();

public void increment() throws InterruptedException {
    Lock lock = this.lock;
    lock.lock();
    try {
        while(increment)
            decremented.await();
        increment = true;           
        c++;
        System.out.println("increment value: " + c);
        incremented.signal();
    } finally {
        lock.unlock();
    }

}

public void decrement() throws InterruptedException {

    Lock lock = this.lock;
    lock.lock();
    try {
        while (!increment)
            incremented.await();
        c--;
        System.out.println("decrement value: " + c);
        increment = false;
        decremented.signal();
    } finally {
        lock.unlock();
    }
}

public int value() {
    Lock lock = this.lock;
    lock.lock();
    try {
        return c;
    } finally {
        lock.unlock();
    }
}

}

答案 2 :(得分:0)

同步器使线程能够彼此等待。请参阅CountDownLatchSemaphore

See Synchronizers section in the java.util.concurrent package

答案 3 :(得分:0)

- 首先,您的increment()decrement()必须使用synchronized关键字以避免竞争条件查看 Brian的规则 < / p>

When we write a variable which has just been read by another thread, or reading a variable which is just lately written by another thread, must be using Synchronization. And those atomic statements/Methods accessing the fields' data must be also synchronized.

- 具有控制权的JVM Thread Scheduler哪个线程将进入运行状态,它将保留多长时间,以及它完成工作后的位置。

- 首先运行一个Cannot be sure个线程.....

- 您还可以使用SingleThreadExecutor中的java.util.concurrent,这样就完成了一项任务,然后再转到第二项任务。