代码如下:
class Q {
int n;
private boolean p = false; synchronized int get() {
if (!p) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Get: " + n);
p = false;
notify();
return n;
} synchronized void put(int n) {
if (p)
try {
wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
this.n = n;
System.out.println("Put: " + n);
p = true;
notify();
}
}class Producer implements Runnable {
Q q; Producer(Q q) {
this.q = q;
new Thread(this, "Producer").start();
} public void run() {
int i = 0;
while (true) {
q.put(i++);
}
}
}class Consumer implements Runnable {
Q q; Consumer(Q q) {
this.q = q;
new Thread(this, "Consumer1").start();
new Thread(this, "Consumer2").start();
new Thread(this, "Consumer3").start();
} public void run() {
synchronized (q) {
while (true) {
q.get();
}
}
}
}class PC {
public static void main(String args[]) {
Q q = new Q();
Thread thread = Thread.currentThread();
new Producer(q);
new Consumer(q);
try {
thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Press Control-C to stop.");
}
}
class Q {
int n;
private boolean p = false; synchronized int get() {
if (!p) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Get: " + n);
p = false;
notify();
return n;
} synchronized void put(int n) {
if (p)
try {
wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
this.n = n;
System.out.println("Put: " + n);
p = true;
notify();
}
}class Producer implements Runnable {
Q q; Producer(Q q) {
this.q = q;
new Thread(this, "Producer").start();
} public void run() {
int i = 0;
while (true) {
q.put(i++);
}
}
}class Consumer implements Runnable {
Q q; Consumer(Q q) {
this.q = q;
new Thread(this, "Consumer1").start();
new Thread(this, "Consumer2").start();
new Thread(this, "Consumer3").start();
} public void run() {
synchronized (q) {
while (true) {
q.get();
}
}
}
}class PC {
public static void main(String args[]) {
Q q = new Q();
Thread thread = Thread.currentThread();
new Producer(q);
new Consumer(q);
try {
thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Press Control-C to stop.");
}
}
Put: 4625
Get: 4625
Get: 4625
Get: 4625
Put: 4626
Get: 4626
Get: 4626
Get: 4626
Put: 4627
Get: 4627
Get: 4627
Get: 4627
请问我是不是哪的锁没有锁好?
一个线程拿出数字后,其他线程就不会再取得同样的数字了。
Put: 778
false
Get: 778
true
Get: 778
false
Get: 778
false
p的值是false的时候生产,true时消费,现在false也消费了
try {
wait(); // 当线程被唤醒,没有重新判断 p 的值,这里 n 的值还是之前的那一个
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}更改之后:class Q {
int n;
private boolean p = false; synchronized int get() {
while(!p) { // 改成 while 就可以了
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Get: " + n + " (" + Thread.currentThread().getName() + ")");
p = false;
notifyAll(); // 改成 notifyAll
return n;
} synchronized void put(int n) {
while(p) { // 改成 while 就可以了
try {
wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
}
this.n = n;
System.out.println("Put: " + n);
p = true;
notifyAll(); // 改成 notifyAll
}
}也可以使用 JDK 5 并发包中的 ReentrantLock 和 Condition 来实现:class Q {
int n;
private boolean p = false;
private final Lock lock = new ReentrantLock();
private final Condition canConsume = lock.newCondition();
private final Condition canProduce = lock.newCondition(); int get() {
lock.lock();
try {
while(!p) {
canConsume.await();
}
System.out.println("Get: " + n + " (" + Thread.currentThread().getName() + ")");
p = false;
canProduce.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return n;
} void put(int n) {
lock.lock();
try {
while(p) {
canProduce.await();
}
this.n = n;
System.out.println("Put: " + n);
p = true;
canConsume.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
int n; private boolean p = false; synchronized int get() {
while (!p) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread() + "--Get: " + n);
p = false;
notifyAll();
return n;
} synchronized void put(int n) {
while (p) {
try {
wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
}
this.n = n;
System.out.println(Thread.currentThread() + "--Put: " + n);
p = true;
notifyAll();
}
}class Producer implements Runnable {
Q q; Producer(Q q) {
this.q = q;
new Thread(this, "Producer").start();
} public void run() {
int i = 0;
while (true) {
q.put(i++);
}
}
}class Consumer implements Runnable {
Q q; Consumer(Q q) {
this.q = q;
new Thread(this, "Consumer1").start();
new Thread(this, "Consumer2").start();
new Thread(this, "Consumer3").start();
} public void run() {
synchronized (q) {
while (true) {
q.get();
}
}
}
}public class PC {
public static void main(String args[]) {
Q q = new Q();
Thread thread = Thread.currentThread();
new Producer(q);
new Consumer(q);
try {
thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Press Control-C to stop.");
}
}
synchronized (q) {
while (true) {
q.get();
}
}
是不是可以不要。还有wait()方法被激活后是不是就往下执行了,不会再重新开始执行函数了吗?谢谢了线程没学好啊呵呵
不能不要!wait() 被唤醒后,会接着执行,而不是从头开始执行。
while (true) {
q.get();
}
我加上了这句后就一直只执行第一个线程,其他的两个就不执行了
Q q; Consumer(Q q) {
this.q = q;
new Thread(this, "Consumer1").start();
new Thread(this, "Consumer2").start();
new Thread(this, "Consumer3").start();
} public void run() {
// 使用 Q 中的 ReentrantLock 锁
// 把 Q 中 lock 的 private 去掉,变成包内可访问
q.lock.lock();
try {
while (true) {
q.get();
}
} finally {
// Lock 接口的锁必须在 finally 中释放掉,便于在有异常时也能正常的释放锁,以免造成死锁
// 而用 synchronized 的话,在抛出异常时 JVM 会自动释放锁
q.lock.unlock();
}
}
}
欢迎加入!