Synchronized 实现生产者消费者:(隐式的加锁)
class ProducerConsumerDemo
{
public static void main(String[] args)
{
Resource r = new Resource();
Producer pro = new Producer(r);
Consumer con = new Consumer(r);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(pro);
Thread t3 = new Thread(con);
Thread t4 = new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
/*
对于多个生产者和消费者。
为什么要定义while判断标记。
原因:让被唤醒的线程再一次判断标记。
为什么定义notifyAll,
因为需要唤醒对方线程。
因为只用notify,容易出现只唤醒本方线程的情况。导致程序中的所有线程都等待。
*/
class Resource
{
private String name;
private int count = 1;
private boolean flag = false;
// t1 t2
public synchronized void set(String name)
{
while(flag)
try{this.wait();}catch(Exception e){}//t1(放弃资格) t2(获取资格)
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
flag = true;
this.notifyAll();
}
// t3 t4
public synchronized void out()
{
while(!flag)
try{wait();}catch(Exception e){}//t3(放弃资格) t4(放弃资格)
System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
flag = false;
this.notifyAll();
}
}
class Producer implements Runnable
{
private Resource res;
Producer(Resource res)
{
this.res = res;
}
public void run()
{
while(true)
{
res.set("+商品+");
}
}
}
class Consumer implements Runnable
{
private Resource res;
Consumer(Resource res)
{
this.res = res;
}
public void run()
{
while(true)
{
res.out();
}
}
}
Lock 实现生产者消费者:(JDK1.5后出现了Lock:显式的加锁)
import java.util.concurrent.locks.*;
class ProducerConsumerDemo2
{
public static void main(String[] args)
{
Resource r = new Resource();
Producer pro = new Producer(r);
Consumer con = new Consumer(r);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(pro);
Thread t3 = new Thread(con);
Thread t4 = new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
/*
JDK1.5 中提供了多线程升级解决方案。
将同步Synchronized替换成现实Lock操作。
将Object中的wait,notify notifyAll,替换了Condition对象。
该对象可以Lock锁 进行获取。
该示例中,实现了本方只唤醒对方操作。
Lock:替代了Synchronized
lock
unlock
newCondition()
Condition:替代了Object wait notify notifyAll
await();
signal();
signalAll();
*/
class Resource
{
private String name;
private int count = 1;
private boolean flag = false;
// t1 t2
private Lock lock = new ReentrantLock();
private Condition condition_pro = lock.newCondition();
private Condition condition_con = lock.newCondition();
public void set(String name)throws InterruptedException
{
lock.lock();
try
{
while(flag)
condition_pro.await();//t1,t2
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
flag = true;
condition_con.signal();
}
finally
{
lock.unlock();//释放锁的动作一定要执行。
}
}
// t3 t4
public void out()throws InterruptedException
{
lock.lock();
try
{
while(!flag)
condition_con.await();
System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
flag = false;
condition_pro.signal();
}
finally
{
lock.unlock();
}
}
}
class Producer implements Runnable
{
private Resource res;
Producer(Resource res)
{
this.res = res;
}
public void run()
{
while(true)
{
try
{
res.set("+商品+");
}
catch (InterruptedException e)
{
}
}
}
}
class Consumer implements Runnable
{
private Resource res;
Consumer(Resource res)
{
this.res = res;
}
public void run()
{
while(true)
{
try
{
res.out();
}
catch (InterruptedException e)
{
}
}
}
}
Synchronized在同步代码块执行完毕或者出现异常时,会自动的释放锁。而Lock在出现异常时不会自动释放锁,所以会写成try(处理代码)finally(lock.unlock)格式防止出现异常时不释放锁的情况。但是在这里出现异常的地方是await(),如果在该地方try.{}..catch(){}一下,就不用外层的try{}..finally{}了,因为异常捕获后会直接往下执行,从而释放锁:如下代码:
package base;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.*;
public class ProducerConsumerDemo2 {
public static void main(String[] args) {
Resource resource=new Resource();
Input input=new Input(resource);
Output output=new Output(resource);
Thread thread1=new Thread(input);
Thread thread2=new Thread(input);
Thread thread3=new Thread(output);
Thread thread4=new Thread(output);
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
}
class Resource{
private String name;
private int count=1;
private boolean flag=false;
private Lock lock=new ReentrantLock();
private Condition condition_pro=lock.newCondition();
private Condition condition_con=lock.newCondition();
public void set(String name)
{
lock.lock();
while(flag){
try {
condition_pro.await();
throw new InterruptedException();
} catch (InterruptedException e) {
//e.printStackTrace();
}
}
this.name=name+"编号"+(count++);
System.out.println(Thread.currentThread().getName()+"生产"+this.name);
flag=true;
condition_con.signal();
lock.unlock();
}
public void out()
{
lock.lock();
while(!flag){
try {
condition_con.await();
throw new InterruptedException();
} catch (InterruptedException e) {
//e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"....消费..."+this.name);
flag=false;
condition_pro.signal();
}
}
class Input implements Runnable{
private Resource res;
public Input(Resource res){
this.res=res;
}
public void run(){
while(true){
res.set("商品");
}
}
}
class Output implements Runnable{
private Resource res;
public Output(Resource res){
this.res=res;
}
public void run(){
while(true){
res.out();
}
}
}
但是如果,await()处不处理异常而是像上面的抛异常给上级,那么就需要try{}...finally{},因为出现异常后,下面的代码将不会执行,锁将不会被释放
一般为安全起见,写第一种方法。