java笔记--多生产多消费问题
2018-07-29 本文已影响0人
吃饱喝足搬代码丶
单一生产者,消费者问题:
class Resource{
private String name;
private int count=1;
private boolean flag=false;
public synchronized void set(String name){
if(flag)
try{
this.wait();
}catch(InterruptedException e){
}
this.name=name+count;
count++;
System.out.println(Thread.currentThread().getName()+"...生产者。。。。。"+this.name);
flag=true;
notify();
}
public synchronized void out(){
if(!flag)
try{
this.wait();
}catch(InterruptedException e){
}
System.out.println(Thread.currentThread().getName()+"...消费者。。。"+this.name);
flag=false;
notify();
}
}
class Producer implements Runnable{
private Resource r;
Producer(Resource r){
this.r=r;
}
public void run(){
while(true){
r.set("kaoya");
}
}
}
class Consumer implements Runnable{
private Resource r;
Consumer(Resource r){
this.r=r;
}
public void run(){
while(true){
r.out();
}
}
}
public class XiaoFei {
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(con);
t1.start();
t2.start();
}
}
运行:
多生产多消费问题:
class Resource{
private String name;
private int count=1;
private boolean flag=false;
public synchronized void set(String name){
if(flag)
try{
this.wait();
}catch(InterruptedException e){
}
this.name=name+count;
count++;
System.out.println(Thread.currentThread().getName()+"...生产者。。。。。"+this.name);
flag=true;
notify();
}
public synchronized void out(){
if(!flag)
try{
this.wait();
}catch(InterruptedException e){
}
System.out.println(Thread.currentThread().getName()+"...消费者。。。"+this.name);
flag=false;
notify();
}
}
class Producer implements Runnable{
private Resource r;
Producer(Resource r){
this.r=r;
}
public void run(){
while(true){
r.set("kaoya");
}
}
}
class Consumer implements Runnable{
private Resource r;
Consumer(Resource r){
this.r=r;
}
public void run(){
while(true){
r.out();
}
}
}
public class Many {
public static void main(String[] args) {
Resource r=new Resource();
Producer pro=new Producer(r);
Consumer con=new Consumer(r);
Thread t0=new Thread(pro);
Thread t1=new Thread(pro);
Thread t2=new Thread(con);
Thread t3=new Thread(con);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
如果直接创建多个线程,会出现生产一次,却消费多次的冲突,或者生产多个,却消费最近一个(即有生产的未被消费)的冲突。
这时可把判断语句if换成while,但会出现死锁现象。所以要在将notify改为notifyAll。即:
//多生產多消費問題
//if判断标记,只有一次会导致不该执行的线程运行了。出现了数据错误的情况
//while判断标记,解决了线程获取执行权后,是否要运行!
//notify只能唤醒一个线程,如果本方唤醒了本方,无意义。而且while判断标记+notify会导致死锁。
//notifyAll解决了,本方线程一定会唤醒对方线程。
class Resource{
private String name;
private int count=1;
private boolean flag=false;
public synchronized void set(String name){
while(flag)
try{
this.wait();
}catch(InterruptedException e){
}
this.name=name+count;
count++;
System.out.println(Thread.currentThread().getName()+"...生产者。。。。。"+this.name);
flag=true;
notifyAll();
}
public synchronized void out(){
while(!flag)
try{
this.wait();
}catch(InterruptedException e){
}
System.out.println(Thread.currentThread().getName()+"...消费者。。。"+this.name);
flag=false;
notifyAll();
}
}
class Producer implements Runnable{
private Resource r;
Producer(Resource r){
this.r=r;
}
public void run(){
while(true){
r.set("kaoya");
}
}
}
class Consumer implements Runnable{
private Resource r;
Consumer(Resource r){
this.r=r;
}
public void run(){
while(true){
r.out();
}
}
}
public class YouHua {
public static void main(String[] args) {
Resource r=new Resource();
Producer pro=new Producer(r);
Consumer con=new Consumer(r);
Thread t0=new Thread(pro);
Thread t1=new Thread(pro);
Thread t2=new Thread(con);
Thread t3=new Thread(con);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
运行:
image.png
JDK1.5以后将同步和锁封装成了对象。并将操作锁的隐式方式定义到了该对象中,将隐式变成了显示动作。
Lock接口:出现替代了同步代码块或者同步函数。将同步的隐式锁操作变成了显式锁操作。同时更为灵活。可以一个锁上加上多组监视器。——lock();unclock();
Condition接口:出现替代了Object中的wait,notify,notifyAll方法。将这些监视器方法单独进行了封装,变成Condition监视器对象。可以任意锁进行组合。——await();singnal();singnalAll();
import java.util.concurrent.locks.*;
class Resource{
private String name;
private int count=1;
private boolean flag=false;
// 创建一个锁对象。
Lock lock=new ReentrantLock();
//通过已有的锁获取该锁上的监视器对象。
// Condition con=lock.newCondition();
//通过已有的锁获取两组监视器,一组监视生产者,一组监视消费者。
Condition producer_con = lock.newCondition();
Condition consumer_con = lock.newCondition();
public void set(String name){
lock.lock();
// try{lock.wait();}catch(InterruptedException e){}
try{
while(flag)
try{
producer_con.await();;
}catch(InterruptedException e){
}
this.name=name+count;
count++;
System.out.println(Thread.currentThread().getName()+"...生产者。。。。。"+this.name);
flag=true;
// con.signalAll();
consumer_con.signal();
}finally{
lock.unlock();
}
}
public void out(){
lock.lock();
// try{this.wait();}catch(InterruptedException e){}
try{
while(!flag)
try{
consumer_con.await();
}catch(InterruptedException e){
}
System.out.println(Thread.currentThread().getName()+"...消费者。。。"+this.name);
flag=false;
// con.signalAll();
producer_con.signal();
}finally{
lock.unlock();
}
}
}
class Producer implements Runnable{
private Resource r;
Producer(Resource r){
this.r=r;
}
public void run(){
while(true){
r.set("kaoya");
}
}
}
class Consumer implements Runnable{
private Resource r;
Consumer(Resource r){
this.r=r;
}
public void run(){
while(true){
r.out();
}
}
}
public class lockandcondition {
public static void main(String[] args) {
Resource r=new Resource();
Producer pro=new Producer(r);
Consumer con=new Consumer(r);
Thread t0=new Thread(pro);
Thread t1=new Thread(pro);
Thread t2=new Thread(con);
Thread t3=new Thread(con);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
运行效果同上。
JDK1.5以后将同步和锁封装成了对象。
并将操作锁的隐式方式定义到了
该对象中,将隐式变成了显示动作。
Lock接口:出现替代了同步代码块或者同步函数。将同步的隐式锁操作变成了显式锁操作。
同时更为灵活。可以一个锁上加上多组监视器。
lock();unclock();
Condition接口:出现替代了Object中的wait,notify,notifyAll方法。
将这些监视器方法单独进行了封装,变成Condition监视器对象。
可以任意锁进行组合。
await();singnal();singnalAll();
wait与sleep的区别:
1.wait可以指定时间也可以不指定。
sleep必须指定时间
2.在同步中时,对cpu的执行权和锁的处理不同。
wait:释放执行权,释放锁。
sleep:释放执行权,不释放锁。
class Resource{
private String name;
private int count=1;
private boolean flag=false;
// 创建一个锁对象。
Lock lock=new ReentrantLock();
//通过已有的锁获取该锁上的监视器对象。
// Condition con=lock.newCondition();
//通过已有的锁获取两组监视器,一组监视生产者,一组监视消费者。
Condition producer_con = lock.newCondition();
Condition consumer_con = lock.newCondition();
public void set(String name){
lock.lock();
// try{lock.wait();}catch(InterruptedException e){}
try{
while(flag)
try{
producer_con.await();;
}catch(InterruptedException e){
}
this.name=name+count;
count++;
System.out.println(Thread.currentThread().getName()+"...生产者。。。。。"+this.name);
flag=true;
// con.signalAll();
consumer_con.signal();
}finally{
lock.unlock();
}
}
public void out(){
lock.lock();
// try{this.wait();}catch(InterruptedException e){}
try{
while(!flag)
try{
consumer_con.await();
}catch(InterruptedException e){
}
System.out.println(Thread.currentThread().getName()+"...消费者。。。"+this.name);
flag=false;
// con.signalAll();
producer_con.signal();
}finally{
lock.unlock();
}
}
}
class Producer implements Runnable{
private Resource r;
Producer(Resource r){
this.r=r;
}
public void run(){
while(true){
r.set("kaoya");
}
}
}
class Consumer implements Runnable{
private Resource r;
Consumer(Resource r){
this.r=r;
}
public void run(){
while(true){
r.out();
}
}
}
public class lockandcondition {
public static void main(String[] args) {
Resource r=new Resource();
Producer pro=new Producer(r);
Consumer con=new Consumer(r);
Thread t0=new Thread(pro);
Thread t1=new Thread(pro);
Thread t2=new Thread(con);
Thread t3=new Thread(con);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
/*
停止线程:
1 stop方法。
2 run方法结束。
怎么控制线程的任务结束呢?
任务中都会有循环结构,只要控制住循环就可以结束任务。
控制循环通常就用定义标记来完成(变量flag)。
但是如果线程处于冻结状态,无法读取标记。如何结束呢?
可以使用interrupt()方法将线程从冻结状态强制恢复到运行状态中来,让线程具备cpu的执行资格。
但是强制动作会发生了InterruptedException,记得要处理。
*/
class StopThread implements Runnable{
private boolean flag=true;
public synchronized void run(){
while(flag){
try{
wait();
}catch(InterruptedException e){
System.out.println(Thread.currentThread().getName()+"....."+e);
flag=false;
}
System.out.println(Thread.currentThread().getName()+".....++++");
}
}
public void setFlag(){
flag=false;
}
}
public class StopThreadDemo {
public static void main(String[] args)
{
StopThread st = new StopThread();
Thread t1 = new Thread(st);
Thread t2 = new Thread(st);
t1.start();
t2.setDaemon(true);
t2.start();
int num = 1;
for(;;)
{
if(++num==50)
{
// st.setFlag();
t1.interrupt();
// t2.interrupt();
break;
}
System.out.println("main...."+num);
}
System.out.println("over");
}
}