juc版本和synchronized版本的区别:
juc这里使用锁需要事先在类里面声明锁,然后用锁获取newCondition,使用condition类即可,以下是jdk,api里面写的
例如,假设我们有一个有限的缓冲区,它支持put和take方法。 如果在一个空的缓冲区尝试一个take ,则线程将阻塞直到一个项目可用; 如果put试图在一个完整的缓冲区,那么线程将阻塞,直到空间变得可用。 我们希望在单独的等待集中等待put线程和take线程,以便我们可以在缓冲区中的项目或空间可用的时候使用仅通知单个线程的优化。 这可以使用两个Condition实例来实现。
class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException {
lock.lock(); try {
while (count == items.length)
notFull.await();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
notEmpty.signal();
} finally { lock.unlock(); }
}
public Object take() throws InterruptedException {
lock.lock(); try {
while (count == 0)
notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
notFull.signal();
return x;
} finally { lock.unlock(); }
}
}
模仿它,我们也来写一个自己的生产者和消费者:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//线程之间的通信问题:生产者和消费者问题!等待唤醒,通知唤醒线程交替执行A B操作同一个变量num = 0
// A num+1
// B num-1
public class B {
public static void main(String[] args) {
Data2 data=new Data2();
new Thread(()->{
for (int i = 0; i <10 ; i++) {
try {
data.product();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(()->{
for (int i = 0; i <10 ; i++) {
try {
data.consumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"B").start();
new Thread(()->{
for (int i = 0; i <10 ; i++) {
try {
data.product();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"C").start();
new Thread(()->{
for (int i = 0; i <10 ; i++) {
try {
data.consumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"D").start();
}
}
class Data2{
private int num=0;
Lock lock =new ReentrantLock();
Condition condition = lock.newCondition();
public void product() throws InterruptedException {
lock.lock();
try {
while (num != 0) {
condition.await();
}
num++;
System.out.println(Thread.currentThread()+"线程生产了1份,当前:"+num);
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void consumer() throws InterruptedException {
// 假如存在虚假唤醒,那么此时的num==0,就进入等待,一直等到num不是虚假唤醒而是真实唤醒变成了1
lock.lock();
try {
while (num == 0) {
condition.await();
}
num--;
System.out.println(Thread.currentThread()+"线程消费了1份,当前:"+num);
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
执行结果:
Thread[A,5,main]线程生产了1份,当前:1
Thread[B,5,main]线程消费了1份,当前:0
Thread[C,5,main]线程生产了1份,当前:1
Thread[B,5,main]线程消费了1份,当前:0
Thread[C,5,main]线程生产了1份,当前:1
Thread[D,5,main]线程消费了1份,当前:0
Thread[C,5,main]线程生产了1份,当前:1
Thread[D,5,main]线程消费了1份,当前:0
Thread[C,5,main]线程生产了1份,当前:1
Thread[D,5,main]线程消费了1份,当前:0
Thread[C,5,main]线程生产了1份,当前:1
Thread[D,5,main]线程消费了1份,当前:0
Thread[C,5,main]线程生产了1份,当前:1
Thread[D,5,main]线程消费了1份,当前:0
Thread[C,5,main]线程生产了1份,当前:1
Thread[D,5,main]线程消费了1份,当前:0
Thread[C,5,main]线程生产了1份,当前:1
Thread[D,5,main]线程消费了1份,当前:0
Thread[C,5,main]线程生产了1份,当前:1
Thread[D,5,main]线程消费了1份,当前:0
Thread[C,5,main]线程生产了1份,当前:1
Thread[D,5,main]线程消费了1份,当前:0
Thread[A,5,main]线程生产了1份,当前:1
Thread[D,5,main]线程消费了1份,当前:0
Thread[A,5,main]线程生产了1份,当前:1
Thread[B,5,main]线程消费了1份,当前:0
Thread[A,5,main]线程生产了1份,当前:1
Thread[B,5,main]线程消费了1份,当前:0
Thread[A,5,main]线程生产了1份,当前:1
Thread[B,5,main]线程消费了1份,当前:0
Thread[A,5,main]线程生产了1份,当前:1
Thread[B,5,main]线程消费了1份,当前:0
Thread[A,5,main]线程生产了1份,当前:1
Thread[B,5,main]线程消费了1份,当前:0
Thread[A,5,main]线程生产了1份,当前:1
Thread[B,5,main]线程消费了1份,当前:0
Thread[A,5,main]线程生产了1份,当前:1
Thread[B,5,main]线程消费了1份,当前:0
Thread[A,5,main]线程生产了1份,当前:1
Thread[B,5,main]线程消费了1份,当前:0