线程唤醒案例, 死锁案例

要求逐一输出(张三--18,李四--20)

1.生产程序

package 生产消费2;
//生产数据
public class set implements Runnable{
   private student s;
   public set(student s) {
	   this.s=s;
   }
   int x=0;
	public void run() {
		while(true) {
			synchronized (s) {//改进后加入锁
			if(x%2==0) {
				s.name="张三";
				s.age=18;
			}else {
				s.name="李四";
				s.age=20;			
	        }
			x++;
		}
	  }
    }
}

2.消费程序

package 生产消费2;
//消费数据
public class get implements Runnable{
    private student s;
    public get(student s) {
    	this.s=s;
    }
	public void run() {
		while(true) {
			synchronized (s) {  //改进后加入的锁
				System.out.println(s.name+"---"+s.age);
			}
		}
		
	}

}

3.main程序

package 生产消费2;
//循环生产循环消费
//运行结果:李四---18
//       张三---20
//运行出现张三和李四的是随机的,不是想象中的逐一出现,且有错误数据
//所以要加入synchronized锁,在此运行
//运行后不再有错误数据,但是依然没有解决重复逐一打印
//原因:加锁之后起到的效果是在生产线程时不会出现数据错乱的效果,
//因为当一个线程进去后,其他线程无法进入,只有等前一个借宿才能进入,
//所以就解决的错误数据的问题
//消费中加入锁无意义,因为只有单一输出,不会有错误
public class rundemo {
    public static void main(String[] args) {
    	//创建学生类对象
		student s=new student();
		//创建线程类对象
		set se=new set(s);
		get ge=new get(s);
		//创建线程对象
		Thread t1=new Thread(se);
		Thread t2=new Thread(ge);
		//启动线程
		t1.start();
		t2.start();
	}
}

二.改进后的唤醒机制

1.生产程序

	package 生产消费3;
	//生产数据
	public class set implements Runnable{
	   private student s;
	  private int x=0;
	   public set(student s) {
		   this.s=s;
	   }
		public void run() {
		while(true) {
			//生产者加锁
			synchronized (s) {
				//判断是否有数据,没有数据则flag为flase
				if(s.flag) {
					//有数据,则s.wait等待,且抛异常
					try {
						s.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
					//生产数据
				    if(x%2==0) {
					   s.name="张三";
					   s.age=18;
				    }else {
					   s.name="李四";
					   s.age=20;			
		            }
				
				   x++;
				   //数据已经生产完,则s.flag是ture,也就是有数据
				   s.flag=true;
				   //唤醒get(消费)
				   s.notify();
		       
		  }
		}
	  } 
	}

2.消费程序

package 生产消费3;
//消费数据
public class get implements Runnable{
    private student s;
    public get(student s) {
    	this.s=s;
    }
	public void run() {
		while(true) {
		    synchronized (s) {
		        if(!s.flag) {
		        	try {
						s.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
		        }
		           System.out.println(s.name+"---"+s.age);
		    s.flag=false;
		    s.notify();
			}
	    }
   }
}

3.main程序

package 生产消费3;
//为了解决逐一打印问题,加入线程等待唤醒机制
//public final void notify()
//唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。
//选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个 wait 方法,在对象的监视器上等待。 
/**
 *   唤醒流程:
 *   两个线程一起执行:
 *   set执行,判断是否有数据,有数据则s.wait()等待,也就是不产出数据
 *                    没数据则则添加数据,添加完后执行s.flag=ture
 *                    将flag更改为错误,也就是有数据,再唤醒等待中的线程(也就是正在执行s.wait()的线程)
 *                    s.notify()唤醒get数据
 *                    get的判断等待的代码就接收到的是ture
 *                    就会输出消费数据
 *   get执行.判断是否有数据,有数据则输出数据,然后执行s.flag=flase
 *                     同是唤醒set数据,来产生数据
 *                    没数据则等待
 *   中间的核心  1.有一个可以判断是否线程等待的boolean类型
 *              2.唤醒机制,可以互相唤醒的功能
 *   这样才实现了逐一输出的结果
 */
public class rundemo {
    public static void main(String[] args) {
    	//创建学生类对象
		student s=new student();
		//创建线程类对象
		set se=new set(s);
		get ge=new get(s);
		//创建线程对象
		Thread t1=new Thread(se);
		Thread t2=new Thread(ge);
		//启动线程
		t1.start();
		t2.start();
	}
}

三.死锁案例

package 死锁现象;

public class demo {
    public static void main(String[] args) {
		lock l1 = new lock(true);
		lock l2 = new lock(false);
		l1.start();
		l2.start();
	}
}
//输出可能的结果
//else objB
//else objA
//if ObjA
//if objB

//if ObjA
//if objB
//else objB
//else objA

//if obgA
//else objB

//else objB
//if obgA


	package 死锁现象;
	//出现锁死的原因:
		/**run中有两个锁,锁对象分别是objA和objB
		 * 在进程l1和l2进来的的时候,
		 * 假设l1先进来(true),那么objA先执行,在执行obj2之前,
		 * l2(flase)进程进来执行了objB
		 * 这时objA和objB都被执行,但if或者else中的语句还没有执行完毕
		 * 继续向下执行,这时就出现了死锁
		 * 因为if中要执行的objB的锁在else中被占中,所以等待else执行完后执行后释放objB,然后if执行
		 * else中要执行的objA的锁在if中被占中,所以等待if执行完后执行后释放objB,然后else执行
		 * 就出现了互相等待的情况,都执行一般等待对方释放,这就是死锁
		 * 但是也有特殊情况:比如if或者else语句都执行完毕后再执行其他语句
		 * 这样就释放了objA和objB的锁,就不会出现死锁情况
		 * 
		 * 
		 * 
		 */
	public class lock extends Thread{
	   private boolean flag;
	   public static final Object objA = new Object() ;
		public static final Object objB = new Object() ;
	   public lock( boolean flag) {
		this.flag=flag;
	}  
	   @Override
	   public void run() {
	   if(flag) {
		   synchronized (objA) {
			   System.out.println("if obgA");
		   synchronized (objB) {
		       System.out.println("if bogB");	
		}
		}
	   }else {
		   synchronized (objB) {
		       System.out.println("else objB");	
		   synchronized (objA) {
			   System.out.println("else objA");
		}
		}
	   }
	}
	}	
	


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值