多线程

来源:互联网 发布:打印机上数据没显示 编辑:程序博客网 时间:2024/05/21 06:28


public class TestCase extends junit.framework.TestCase{
 
 //进程:正在执行中的程序,每一个进程执行都有执行的顺序,该顺序是一个执行路径或控制单元,至少有一个线程
 //线程:进程中真正执行的部分,控制着进程的执行,


 /*创建线程
  * 1、集成Thread类,复写Thread类的run方法(Thread类中的run方法,用于存储线程要运行的代码)
  * 2、实现Runable接口,覆盖run方法,通过Thread建立线程对象,将runable接口的子类对象传递给Thread的构造函数
  * 调用Thread类的start方法
  * 两种方法的区别
  * 避免单继承的局限性(建议使用Runnable)
  *
  * Thread.currentThread获取当前线程对象,静态的
  * */

class Thread1 extends Thread{

      public void run(){

       }

}

classThread2 implements Runnable{

   public void run(){

}

}
 
/*
 * 多线程的运行出现安全问题
 * 问题的原因:当多条语句在操作同一个共享数据时,一个线程对多条语句只执行了一部分,就切换了另一个线程
 * 解决办法:
 *  对多条操作共享数据的语句,只能让一个线程都执行完,执行过程中,不让其他线程执行
 * 同步代码块:锁
 * synchronized(对象){
 *  
 * }
 * 同步的前提:至少两个以上的线程,多个线程使用一个锁,必须是一个线程执行
 * 好处:解决了安全问题
 * 弊端:消耗资源,判断锁
 * 如何找问题:
 * 1、明确哪些代码是多线程运行代码
 * 2、明确共享数据
 * 3、明确多线程运行代码中哪些语句是操作共享数据的
 *
 * 同步函数:public synchronized void add(){}
 * 同步函数用的锁:函数需要被对象调用,那么函数都有一个所属对象引用,就是this.所以同步函数使用的就是this
 * 如果同步函数被static修饰,锁不是this,因为静态方法中不可以定义this
 * 静态进内存,内存中没有本类对象,但是一定有该类对应的字节码文件对象
 * 类名.class 该对象的类型是class
 * 静态的同步方法,使用的锁是该方法所在类的字节码文件对象。类名.class
 */

 public void test2(){
  Ticket t = new Ticket();
  Thread t1 = new Thread(t,"1号窗");
  Thread t2 = new Thread(t,"2号窗");
  Thread t3 = new Thread(t,"3号窗");
  Thread t4 = new Thread(t,"4号窗");
  t1.start();
  t2.start();
  t3.start();
  t4.start();
 }
}

class DemoRun extends Thread{
 //private String name;
 //DemoRun(String name){
 // this.name=name;
 //}
 DemoRun(String name){
  super(name);
  }
 public void run(){
  for(int i=0;i<50;i++)
  System.out.println(Thread.currentThread().getName()+"demorun ==="+i);
 }
 
}

class Ticket implements Runnable{
 
 private int ticket=100;
 Object ob =new Object();
 public void run(){
  while(true){
   //同步代码快
   synchronized(ob){//ob锁,线程进去,锁关闭,其他线程进不来。出去释放锁,其他线程进入
    if(ticket>0){
     System.out.println(Thread.currentThread().getName()+"ticket-no-"+ticket--);
    }
   }
  }
 }
}

class Tickets implements Runnable{
 
 private int ticket=100;
 Object ob =new Object();
 public void run(){
  while(true){
    show();
   }
 }
 //同步程序
 public synchronized void show(){
  if(ticket>0){
   System.out.println(Thread.currentThread().getName()+"ticket-no-"+ticket--);
  }
 }
}

//单例(饿汉式)
class SingleOne{
 private static final SingleOne s = new SingleOne();
 private SingleOne(){}
 public static SingleOne getInstance(){
  return s;
 }
}


//单例(懒汉式)  懒汉式在多线程调用时线程不安全,可采用同步解决,同步代码块(
//双重判断用的锁是该类对应的字节码文件对象)与同步函数
class SingleTwo{
 private static SingleTwo s = null;
 private SingleTwo(){}
 public static SingleTwo getInstance(){
  if(s==null){
   synchronized (SingleTwo.class) {
    if(s==null){
     s = new SingleTwo();
    }
   }
  }
  return s;
 }
}

/*
 * 死锁
 * 同步中嵌套同步
 */

 

 

-------------------------------------------------------------------//JDK1.5以后对锁进行了升级-----------------------------------------------------------------------

 

 /*
   * 线程间通信:
   * 多个线程在操作同一个资源,但操作动作不同
   *
   * 等待唤醒机制
   * wait notify  notifyAll 都是用在同步中,因为要对持有监视器(锁)的线程操作
   * 所以要使用在同步中,因为只有同步才具有锁。定义在Object中
   * 等待和唤醒必须是同一把锁,锁是任意对象
   *
   * 当多个生产者与多个消费者  要用while循环判断,
   * 用notifyAll唤醒所有线程,(会出现问题),需要生产者等待时唤醒消费者,消费者者等待时唤醒生产者

   * jdk1.5后提供Lock接口,通过lock实例化Condition接口,Condition 将 Object 监视器方法(waitnotifynotifyAll)分解成截然不同的对象

  * 始终用的是同一把锁,不会出现死锁现象
   */
 public void test1(){

  //实例化资源(两个生产者,两个消费者,生产一个消费一个)
  Resource r = new Resource();
  new Thread(new Producer(r)).start();
  new Thread(new Consumer(r)).start();
  new Thread(new Producer(r)).start();
  new Thread(new Consumer(r)).start();
  
 }
 
 
}
//放进去取出来

//资源类,用于生产商品和消费商品
class Resource{
 private String name;//商品名称
 private int count;   //商品编号
 private boolean flag; //用于判断,资源类中是否有商品存在
 private Lock lock = new ReentrantLock();//创建锁
 private Condition condition_pro = lock.newCondition();//创建Condition  代表生产者
 private Condition condition_con = lock.newCondition();//代表消费者
 public void set(String name) throws InterruptedException{ //生产商品
  lock.lock();//获取锁
  try{
   while(flag)   //循环判断当资源库中有商品时,生产者等待
    condition_pro.await();
   this.name = name+"--"+count++;
   System.out.println(Thread.currentThread().getName()+"-pro-"+this.name);
   flag = true;
   condition_con.signal();//唤醒消费者,消费者获得执行资格,还没有执行权,此时生产者继续进行,到上面await()那冻结
  }finally{
   lock.unlock(); //结束时必须将锁释放
  }
 }
 //消费者
 public void out() throws InterruptedException{
  lock.lock();
  try{
   while(!flag)
    condition_con.await();
   System.out.println(Thread.currentThread().getName()+"-con-"+this.name);
   flag = false;
   condition_pro.signal();
  }finally{
   lock.unlock();
  }
 }
}

//创建生产者线程
class Producer implements Runnable{
 private Resource r;
 Producer(Resource r){
  this.r=r;
 }
 public void run(){
  while(true){
    try {
     r.set("打狗棒");
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
   }
  }
}

//创建消费者线程
class Consumer implements Runnable{
 private Resource r;
 Consumer(Resource r){
  this.r=r;
 }
 public void run(){
  while(true){
   try {
    r.out();
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
 }
}

 


 

 

0 0