多线程系列(二)

来源:互联网 发布:2 100 mod5 编程 编辑:程序博客网 时间:2024/06/11 15:16

一:写一个煤矿例子,一个线程运煤,一个拉煤;
day12-02-多线程(线程间通信-解决安全问题)
class Res{
private String name;
private String sex;
}

class Input implements Runnable{
  Res r;
  public Input(Res r){
  this.r = r;
   }
  public void run(){
     while(true){
       Synchronized(r){
          int x =0
            if(x==0){
                    r.name = "abc";
                    r.sex = "man";
              }else{
                      r.name="ddd";
                      r.sex="women";
                 }
               x = (x+1)%2;
            }
       }
     }
}

class Output implements Runnable{
   Res r;
   public Output(Res r){
   this.r = r;
   }
   public void run(){
               Synchronized(r){    
               System.out.println("Name="+r.name+".........Sex="+r.sex);
             }
    }
  }

public class InputOutputDemo{
  public static void main(String[] args){
    Res r = new Res();
   
    Input input= new Input(r);
   Output output = new Output(r);

   input.start();
   output.start();
}

总结:这里面存在两个线程,拥有两个资源,如果需要同步需要在两个run中都加Synchronized,并且Synchronized锁对象只能为同一个资源,不能为this,可以为Input.class或Output.class或Res;才能正常锁住,不然都会存在问题;
二:day12-03-多线程(线程间通信-等待唤醒机制)
wait、notify、notifyAll
都使用在同步中,因为要对持有监视器(锁)的线程进行操作;
所以要使用在同步中,因为只有同步才具有锁;

为什么这些操作线程的方法都要定义在Object类中呢?
因为这些方法在操作同步时,都要标识它们所操作的线程只有锁;
只有同一个锁上被等待的线程,才能被同一个锁上的notify唤醒,不可能对不是同一个锁上的线程进行notify唤醒;也就是说,等待和唤醒都必须是同一个锁;
而锁也可以是任意对象,所以可以被任意对象调用的方法定义在Object类中;

三:day12-05-多线程(线程间通信-生产者消费)
考察点:
唤醒线程后,需要每次唤醒都校验下flag标记,改if为while;
用notify只能用作两个线程分别做两件事情,如果多于两个线程,同时做两件事情,用notify只能唤醒自己,需要更改notify为
notifyAll方法来处理,具体代码如下:

 class Resoure{
 private String name;
 private int count = 1;
 private boolean flag = false;
  public Synchronized void set(String name){    
    while(flag){
       try{ this.wait();}catch(Exception ex){}  
     this. name = name +"----name----"+count++;
   System.out.println("生产者="+Thread.currentThread.getName()+"+++++++++++++"+count);
   this.flag = true;
   this.notifyAll();
     }
   }
   public Synchronized void out(){
  
     while(!flag){
      try{this.wait();}catch(Exception ex){}
    System.out.println("消费者="+Thread.currentThread.getName()+"-------------------------"+count);
    this.flag = false;
    this.notifyAll();
     }
  }
}

class Prodocer implements Runnable{
 private Resoure res;
 public Prodocer(Resoure res){
   this.res = res;
  }
public void run(){
   while(true){
     res.set("abc");
   }
 
 }
}
 class Consumer implements Runnable{
  private Resoure res;
  public Consumer(Resoure res){
  this.res= res;
  }
  public void run(){
    while(true){
   res.out();
    }
  
 }
}

public class ProdocerOrConsumerDemo{
  public static void main(String[] args){
     Resoure res = new Resoure();
     Prodocer pro= new Prodocer(res);
    Consumer con = new Consumer(res);
  
   Thread thread1 = new Thread(pro);
   Thread thread2 = new Thread(pro);
   Thread thread3 = new Thread(con);
   Thread thread4 = new Thread(con);
  
   thread1.start();
   thread2.start();
   thread3.start();
   thread4.start();
}


四:day12-05-多线程(线程间通信-生产者消费) 启用JDK新特性 LOCK
 class Resoure{
 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)throws IntenException{    
   lock.Lock();
    while(flag){
       try{
        condition_pro.await();
     this. name = name +"----name----"+count++;
   System.out.println("生产者="+Thread.currentThread.getName()+"+++++++++++++"+count);
   this.flag = true;
   condition_con.single();
   }finally{lock.unLock();}
     }
   }
   public void out()throws IntenException{
   lock.Lock();
     while(!flag){
     try{
        condition_con.await();
         System.out.println("消费者="+Thread.currentThread.getName()+"-------------------------"+count);
    this.flag = false;
    condition_pro.single();
      }finally{lock.unLock();}
     }
  }
}

class Prodocer implements Runnable{
 private Resoure res;
 public Prodocer(Resoure res){
   this.res = res;
  }
public void run(){
   while(true){
    try{
     res.set("abc");
      }catch(Exception ex){}
   }
 
 }
}
 class Consumer implements Runnable{
  private Resoure res;
  public Consumer(Resoure res){
  this.res= res;
  }
  public void run(){
    while(true){
    try{  res.out();}catch(Exception ex){}
    }  
 }
}

public class ProdocerOrConsumerDemo{
  public static void main(String[] args){
     Resoure res = new Resoure();
     Prodocer pro= new Prodocer(res);
    Consumer con = new Consumer(res);
  
   Thread thread1 = new Thread(pro);
   Thread thread2 = new Thread(pro);
   Thread thread3 = new Thread(con);
   Thread thread4 = new Thread(con);
  
   thread1.start();
   thread2.start();
   thread3.start();
   thread4.start();
}

//总结:single方法只唤醒对方线程,不会唤醒自己;通过Condition可以控制多个对象,Lock是线程中的显示方式实现,而同步是隐式方式实现。

五:day12-07-多线程(停止线程) ---interupte方法实现
stop方法已经过时,那么如何停止一个线程?
只有一种方法就是让run方法结束;
只要控制住循环,就可以让run方法结束,线程就停止了;
特殊情况:
当线程处于冻结状态时,可以采用以下代码:
while(flag){
try{
   wait();
}catch(InterupteException ex){
   //ex
   flag = true;
  }
}
当在其它地方调用了该线程的interupte方法后,线程会强制从冻结状态抛出interupteException,然后再回到运行状态;

六:day12-08-多线程(守护线程)
setDaemon(true),true为守护线程/后台线程,但前台线程/用户线程运行完毕,守护线程自然就结束;守护线程跟用户线程存在互相依赖的关系,可以通过isDaemon方法来判断是否是守护线程,setDaemon方法必须使用在线程开启方法前;

七:day12-09-多线程(Join方法)
join用来临时加入线程运行,例如A线程运行到B线程调用join方法后,A线程会等到B线程运行完毕后才运行;

八:day12-10-多线程(优先级yield方法)
优先级默认为5,一般为0-10,可以通过setPriority设置优先级;
Thread.yield、wait等都是运行是主线程,如果是其它线程对象调用yield方法,是用来暂停该线程,让其他线程进行争取CPU执行权;

原创粉丝点击