在中国并发这个词已经非常常见了,比如双十一购物狂欢节的淘宝,过年回家的春运12306,这都是我们生活中的并发。在短时间内大量集中的访问一个服务器。然而Java又是解决并发的一把好手,下面简单介绍一下多线程案例的经典案例,生产者和消费者
。
synchronized方法
/**
* 描述资源类
*/
public class factory {
/**用来判断是否需要生产的标志,同时模拟资源*/
private int repertory = 0;
/**
* 工厂的生产方法
*/
public synchronized void product() {
// 判断是否需要生产,如果不需要生产则进入等待状态
while(repertory != 0) {
try{
this.wait();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
repertory++;
System.out.println(Thread.currentThread().getName() + "生产," + "目前库存:" + repertory);
// 唤醒消费者
this.notifyAll();
}
public synchronized void consumer() {
// 判断是否可以消费,如果不可以消费,则进入wait状态
while(repertory == 0) {
try{
this.wait();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
repertory--;
System.out.println(Thread.currentThread().getName() + "消费," + "目前库存:" + repertory);
// 唤醒生产者
this.notifyAll();
}
}
代码实现二:synchronized代码块
public class Factory {
/**用来判断是否需要生产的标志,同时模拟资源*/
private int repertory = 0;
/**
* 生产方法
*/
public void product() {
synchronized(this) {
// 判断是否需要生产,如果不需要生产则进入等待状态
while(repertory != 0) {
try{
this.wait();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
repertory++;
System.out.println(Thread.currentThread().getName() + "生产," + "目前库存:" + repertory);
// 唤醒消费者
this.notifyAll();
}
}
public void consumer() {
synchronized(this) {
while(repertory == 0) {
try{
this.wait();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
repertory--;
System.out.println(Thread.currentThread().getName() + "消费," + "目前库存:" + repertory);
// 唤醒生产者
this.notifyAll();
}
}
}
代码实现三:lock锁
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Factory {
/**用来判断是否需要生产的标志,同时模拟资源*/
private int repertory == 0;
/**定义锁*/
private final Lock lock = new ReetrantLock();
/**控制生产方法运行*/
private final Condition product = lock.newCondition();
/**控制消费方法运行*/
private final Condition consumer = lock.newCondition();
public void product() {
lock.lock();
try{
// 判断是否需要生产,如果不需要生产则停止生产
while(repertory != 0) {
try{
product.await();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
repertory++;
System.out.println(Thread.currentThread().getName() + "生产," + "目前库存:" + repertory);
// 唤醒消费者
consumer.signal();
} finally{
lock.unlock();
}
}
public void consumer() {
lock.lock();
try{
while(repertory == 0) {
try{
consumer.await();
} catch(interruptedException e) {
e.printStackTrace();
}
}
repertory--;
System.out.println(Thread.currentThread().getName() + "消费," + "目前库存:" + repertory);
// 唤醒生产者
product.signal();
} finally {
lock.unlock();
}
}
}
测试类
public class Demo {
public static void main(String[] args) {
Factory goods = new Factory ();
new Thread(() -> {
for (int i = 0; i {
for (int i = 0; i {
for (int i = 0; i {
for (int i = 0; i < 100; i++) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
goods.consumer3();
}
}, "消费者2").start();
}
}
注意事项
在前两种方式中wait
和notify
和notifyAll
方法必须写在同步代码块中。
在判断是否工作时最好使用while
进行判断,防止线程的虚假唤醒。
在前两种方式中,唤醒都是随机唤醒的,而在第三中方式中唤醒的带有准确性唤醒的,一对一唤醒,不存在随机性。
代码写完,小弟知识浅薄,各路大神如果看出问题,可以帮我指正,我及时修改!!!