黑马程序员_11线程同步问题、生产者消费者问题

来源:互联网 发布:淘宝怎么用花呗支付 编辑:程序博客网 时间:2024/06/11 20:01
------- android培训ios培训、期待与您交流! ----------
一、线程同步问题
public class TestSynchThread implements Runnable{
 static int k = 100;
 public synchronized static void m1(){
  k=1000;
  try{
   Thread.sleep(1100);
   System.out.println("子线程执行结果k:"+k);
  }catch(InterruptedException e){
   return;
  }
 }
 
/*m2方法加锁之后,程序最终的输出结果是:子线程执行结果K:1000,MAIN线程执行结果:1000,为什么main线程也是1000呢,是因为t1线程执行完成之后,紧接着执行m2方法,但是M2方法却睡了,此时,直接跳入执行下一个语句,输出了结果。但是如果,t1线程睡眠的时间大于m2方法的休眠时间,那么结果又会出现不同*/
 public synchronized  static void m2(){   
  try{
   Thread.sleep(2000);
  }catch(InterruptedException e){
   return;
  }
k=2000;
 }
 
 public static void main(String[] args){
  TestSynchThread tst = new TestSynchThread();
  Thread t1 = new Thread(tst);
  t1.start();
  tst.m2();
  System.out.println("main 线程执行结果:"+k);
 }
 public void run(){
  m1();
 }
          }
//输出结果为:子线程执行结果k:1000;main线程执行结果:2000;
分析原因:首先执行t1线程,K的值变为1000;此时main线程同时也在执行,但是由于m2方法中,线程sleep为2秒,而t1线程只sleep 1秒,所以t1线程先输出了“子线程执行结果”,之后M2方法在完成2秒的睡眠后,开始执行,并将k的值设置为2000,最后主线程输出结果为2000。这里如果M2方法不加锁,就需要根据睡眠时间的长短来判断K的值了
但是如果M2方法此时加锁之后,输出结果就会出现不同。

二、生产者消费者问题
public class TestSynchThread2{
 public static void main(String[] args){
  WotouSynStack wss = new WotouSynStack();
  Thread t1 = new Thread(new Producer(wss));
  Thread t2 = new Thread(new Consumer(wss));
  t1.start();
  t2.start();
 }
}

class Wotou{
 int id=0;
 int index=0;
 Wotou(int id){
  this.id=id;
 }

 public String toString(){
  return "Wotou--Id:" + id;
 }
}
class WotouSynStack{
 Wotou[] arrWt = new Wotou[6];
 int index=0;
 public synchronized void push(Wotou wt){ //添加时,可以不需要返回值
  if(index == arrWt.length){ //原来的判断是小于这里判断的条件需要修改为==,而且要注意判断语句控制的范围
   try{
    this.wait();//要使用wait方法必须主要配合notify方法使用
   }catch(InterruptedException e){
    e.printStackTrace();
   }
  }
   this.notify();
   arrWt[index]=wt;
   index++;
 }
 public synchronized Wotou pop(){ 
             //这里不需要有参数因为拿出来得时候默认从数组中拿出
  //wts[index]=wt;
  //index--;
   if(index==0){
              //注意这里的判断用的是if才行 ,用while有问题
    try{
               //这里使用wait方法而不能使用sleep方法
     this.wait();
    }catch(InterruptedException e){
     e.printStackTrace();
    }
   }
   this.notify();
   index--;
   return arrWt[index];
 }
}

class Producer implements Runnable{
 WotouSynStack wss = null;
 Producer(WotouSynStack wss){
  this.wss=wss;
 }
 public void run(){
  for(int i=0;i<20;i++){
             //这里是使用构造方法创建对象,而却糊里糊涂使用了数组,提示不兼容的对象,就要看看返回值问题
   Wotou wt =new Wotou(i);
   wss.push(wt);
   System.out.println("生产了:"+wt);
   try{
    Thread.sleep(100); //这里很重要如果不进行睡眠的话,会一直生产
   }catch (InterruptedException e){
    e.printStackTrace();
   }
  }
 }

}

class Consumer implements Runnable{
 WotouSynStack wss = null;
 Consumer(WotouSynStack wss){
  this.wss = wss;
 }
 public void run(){ //这里少了一个for循环取出所以,每次输出结果都只有一个consumer
  for(int i=0;i<20;i++){
   Wotou wt = wss.pop();
   System.out.println("消费了:"+wt);
    try{
     Thread.sleep(1000); //这里很重要 ,这样才能清晰看出
    }catch (InterruptedException e){
     e.printStackTrace();
    }
  }
 }
}

//错误提示问题说明:

//错误提示问题说明:

出现这个错误的原因主要是:程序里面少写了一个大括号
0 0
原创粉丝点击