生产者消费者模式

使用同步机制的这种方式解决线程安全问题,锁对象在哪里释放锁.

Lock锁:

Lock实现提供一个更具体的锁对象:Lock

Lock实现提供了更广泛的锁定操作

Lock是一个接口, ReentrantLock子实现类     lock()获取锁,unlock()试图释放此锁

 

public class SellTicket implements Runnable {

    private int tickets=100;

    private Lock lock =new ReentrantLock();

    @Override

    public void run() {

       while(true){

       try{

       lock.lock();

       if(tickets>0){

           try {

              Thread.sleep(100);

           } catch (InterruptedException e) {

              e.printStackTrace();

           }

           System.out.println(Thread.currentThread().getName()+":"+(tickets--));

       }

       }

       finally{

           lock.unlock();

       }  

    }

    }  

}

 

Try…finally(里面unlock());

 

使用同步机制解决了多线程的安全问题:但是存在弊端.

1.  同步导致执行效率(加锁解锁)

2.     容易出现死锁现象

 

当有两个锁同时加时:会导致死锁:

Eg:

public void run() {

private boolean flag ;

         publicDieLock(boolean flag){

                  this.flag= flag ;

         }

                  if(flag){

                          synchronized(MyLock.objA){

                                   System.out.println("ifobjA");

                                   synchronized(MyLock.objB) {

                                            System.out.println("ifobjB");

                                   }

                          }//代码执行完毕,objA锁相当于才能被释放掉

                  }else{

                          //dl2

                          synchronized(MyLock.objB) {

                                   System.out.println("elseobjB");

                                   synchronized(MyLock.objA){

                                            System.out.println("elseobjA");

                                   }

                          }

                  }

 

一个锁无法释放:线程执行随机性:

导致死锁现象

死锁线程:两个或者两个以上的线程出现了互相等待的情况,就会出现死锁!

 

消费者-生产者模式:

建立学生类:Student类.

生产者模式:SetThread类:

消费者模式:GetThread类:

测试类:StudentDemo,实现多线程环境

学生类:

public class Student {

private String name;

private int age;

}

生产者模式:

public class SetThread implements Runnable {

    private Student s;

    public SetThread(Student s){

       this.s=s;

}

    @Override

    public void run(){

       s.name = "龙哥" ;

       s.age = 20;

    }

    }

Run()方法里面设置名字和年龄.

消费者模式:

public class GetThread  implements Runnable{

    private Student s;

    public GetThread(Student s){   

     this.s=s;

    }

    @Override

    public void run() {

     System.out.println(s.name+"--"+s.age);  

    }

}

Run()方法获取姓名和年龄.

对于每一个线程都在创建自己的学生对象,两个线程操作的两个对象而不是同一个对象,所以应该解决:

将学生对象成员变量,然后通过构造方法进行传递,在测试类中,创建学生对象(同一个资源对象)让多个线程对这个学生对象进行操作

 

为了数据多并且效果更明显,加入循环语句进行操作,给生产者线程和消费者线程分别加入循环语句(while循环)

 

改进后的生产者消费者模式:

生产者模式:

public class SetThread implements Runnable{

    private Student s;

    private int x=0;

    public SetThread(Student s){

      this.s=s;

      }

    @Override

    public void run() {

    while(true){

       synchronized(s){

           if(x%2==0){

              s.name="UZI";

               s.age=21;

           }else{

              s.name="Faker";

              s.age=22;

           }

           x++;

       }

    }

    }   

}

消费者模式:

public class GetThread implements Runnable{

private Students;

public  GetThread(Student s){

    this.s=s;

}

  @Override

  public void run(){

      while(true){

         synchronized(s){

             System.out.println(s.name+"--"+s.age);

         }

      }

  }

}

 

输出的数据为   null-0时   在set ()get()里面创建学生对象

将学生对象成员变量,然后通过构造方法进行传递,

在测试类中,创建学生对象(同一个资源对象)让多个线程对这个学生对象进行操作

改进后的情况:

同一个数据输出多次

且姓名年龄不符合:线程的随机性导致

当前多线程有安全问题:

多线程安全问题的标准:

1)是否是多线程环境

2)是否有共享数据

3)是否有多条语句对共享数据操作

 

再改建:使用synchronized 同步锁对象

保证线程的安全性

新的问题:数据打印一次打印好多.

 

 

需求:一次输出一条,轮换输出:

利用等待唤醒机制.

改进:

Student类:

public class Student {

         Stringname;

         intage ;

         booleanflag ; //默认false,true有数据

生产者模式里面:

While(true)

在同步锁对象里面进行线程等待

调用   s.wait():

while(true){

                          synchronized(s) {

                                   if(s.flag){

                                            try{

                                                     s.wait();//使线程等待

                                            }catch (InterruptedException e) {

                                                     e.printStackTrace();

                                            }

                                   }

 

s.flag = true;// 修改:flag: 

s.notify() ;// 下来唤醒线程状态:

 

消费者模式里面:

Run()方法里面:

while(true){

         synchronized(s) {

         if(!s.flag){

         try{

                  s.wait();//调用的时候,会立即释放锁

         }catch (InterruptedException e) {

         e.printStackTrace();

}

         }

         System.out.println(s.name+"---"+s.age);

         s.flag= false ;//消费者线程   .修改为false

         s.notify();//唤醒t1线程....

}

 

生产者-消费者模式

最终的改进:

将资源对象Student的成员变量私有化

给类中提供两个方法

在两个线程中调用方法.

学生类:

public class Student {

private String name;

private int age;

private boolean flag;

//生产者模式的方法

public synchronized void set(String name,int age){

       if(this.flag){

       try{

           this.wait();

} catch (InterruptedException e) {

    e.printStackTrace();

}

    }

this.name = name ;

       this.age = age ;//产生数据

       this.flag=true;//有数据了,可以使用get()

        this.notify();//唤醒状态

}

//消费者模式的放法

public synchronized void get(){

    if(!this.flag){

       try {

           this.wait();

       } catch (InterruptedException e) {

           e.printStackTrace();

       }

    }

    System.out.println(this.name+"-"+this.age);

    //线程t1t2分别调用Set()  Get()

    this.flag=false;//没有数据了 ,需要生产数据通知线程t1,生产线程

    this.notify();//唤醒t1线程

}

}

 

生产者模式:

public class SetThread implements Runnable{

private Student s;

public SetThread(Student s){

    this.s=s;

}

private int x=0;

@Override

public void run(){

        while(true){

        if(x%2==0){

            s.set("UZI", 20);

        }else{

            s.set("Faker", 21);

        }

          x++;        

    }

}

}

 

消费者模式:

public class GetThread implements Runnable{

private Student s;

public  GetThread(Students){

    this.s=s;

}

   @Override

   public void run(){

       while(true){

          s.get();

       }

   }

}

 

测试类:

public class StudentDemo {

public static void main(String[] args) {

    Student s = new Student();

    SetThread st = new SetThread(s);

    GetThread gt = new GetThread(s);

    Thread s1 = new Thread(st);

    Thread s2 = new Thread(gt);

    s1.start();

    s2.start();

}

}

 

 

线程组:

MyRunnable:

public class MyRunnable implements Runnable{

@Override

public void run(){

    for(int x=0;x<100;x++){

       System.out.println(Thread.currentThread().getName()+"-"+x);

    }

}

}                       

测试类:

 

public class ThreadGroupDemo {

public static void main(String[] args) {

       method();//设置线程名称

}

 

private static void method() {

    //设置线程组名称

    ThreadGroup tg = new ThreadGroup("LONG");

    //创建资源对象

    MyRunnable mr = new MyRunnable();

    Thread s1 = new Thread(tg,mr,"first");

    Thread s2 = new Thread(tg,mr,"second");

    //获取线程组名称的第一种方法

    System.out.println(s1.getThreadGroup().getName());

    System.out.println(s2.getThreadGroup().getName());

    //获取线程组名称的第二种方法

    ThreadGroup tg1=s1.getThreadGroup();

    ThreadGroup tg2=s2.getThreadGroup();

    System.out.println(tg1.getName());

    System.out.println(tg2.getName());

    tg.setDaemon(true);

    s1.start();

    s2.start();

}

}

 

 

线程池:

节约成本:子线程调用完后,不会立即收到,回到线程池多次利用

增加Executors工厂类产生线程池:

//public static ExecutorServicenewFixedThreadPool(int nThreads)

Executors工厂类中的这个方法参数直接指定在当前线程池中有多少个线程

int nThreads  为数字:指定线程个数.

方法返回值为ExecutorService:表示一个线程池,可以执行Runnable对象或者Callable对象代表的线程.

ExecutorService:接口中的方法

Future<?> submit(Runnable task)

测试类:

public class ExcutorsDemo {

public static void main(String[] args) {

    //创建线程池对象,使用Executors工厂类

    ExecutorService pool = Executors.newFixedThreadPool(2);

    //提交多个任务

    pool.submit(new MyRunnable());

    pool.submit(new MyRunnable());

    //结束线程池

    pool.shutdown(); 

}

}

 

 

多线程实现方式:第三种:实际用到少

public class MyCallable implements Callable<Object> {

    @Override

    public Object call() throws Exception {

       for(int x=0;x<100;x++){

           System.out.println(Thread.currentThread().getName()+"-"+x);

       }

              return null;

    }

}

测试类:与线程池一直:

1.     创建线程池对象

2.     提交Callable任务:eg:Threadpool.submit(new MyCallable()) ;

相当于线程中start()方法。

3.结束线程池

 

 

 

JavaSe中的计时器:

常用方法:

Public void schedule(TimerTask task,Datetime)安排在指定的时间执行任务

Public void schedule(TimerTask task,longdelay)在多少毫秒后执行指定任务

Public void schedule(TimerTask task,longdelay,long_period)

在多少毫秒后执行任务,且每多少毫秒重复执行

 

Public void cancel()终止此计时器,舍弃所有当前已安排的任务

 

一:定义一个任务类: 创建一个计时器,任务在多长时间后执行。之后结束任务

public class TimerDemo {

public static void main(String[] args) {

    Timert = new Timer();

    t.schedule(new MyTask(t), 5000);

}

}

//一个任务类:MyTask

class MyTask extends TimerTask{

    private Timert;

    public MyTask(){

    }

    public MyTask(Timer t){

       this.t=t;

    }

    @Override

    public void run() {

    System.out.println("任务结束.");

    t.cancel();//终止t计时器,舍弃任务

    }

}

 

二:一个任务类:在多少毫秒后执行,且没多少毫秒重复执行

import java.util.Timer;

import java.util.TimerTask;

public class TimerDemo2 {

public static void main(String[] args) {

    Timer t = new Timer();

    t.schedule(new MyStack2(),3000 , 2000);

}

}

class MyStack2 extends TimerTask{

    @Override

    public void run() {

       System.out.println("两秒后重复执行");

    }  

}

 

 

 

在指定时间递归删除目录:

public class DeleteFolder extends TimerTask {

    @Override

    public void run() {

       // 封装当前项目下的demo文件

       File srcFolder = new File("Demo");

       deleteFolder(srcFolder);

    }

    private void deleteFolder(File srcFolder) {

     //获取当前srcFolder下的所有文件以及File数组

       File[] FileArray = srcFolder.listFiles();

       if(FileArray!=null){

           for(File file:FileArray){

              //判断是否为文件夹

              if(file.isDirectory()){

                  deleteFolder(file);

              }else{//文件直接删除

              System.out.println(file.getName()+"--"+file.delete());

              }

           }

           System.out.println(srcFolder.getName()+"--"+srcFolder.delete());

       }

    }

    public static class TimerTest {

       public static void main(String[] args) throws ParseException {

           Timer t = new  Timer() ;

           String dateStr = "2017-12-714:49:00" ;

           //创建SimpleDateFormat对象

           SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") ;

           Date date = sdf.parse(dateStr) ;

           t.schedule(new DeleteFolder(), date) ;

       }

}

}

 

多线程的匿名内部类:

格式:

new 类名(具体类,抽象类),接口(){

                  重写/实现方法;

}                       

Eg:

继承自Thread类

new Thread(){

@Override

         public void run() {

        for(int x = 0 ; x <100 ; x ++){

                          System.out.println(Thread.currentThread().getName()+":"+x);

                  }

            }

            }.start() ;//启动线程

Runnable 接口的方式:

            new Thread(new Runnable() {

                         

                          @Override

                          public void run() {

                                   //for循环

                                   for(int x = 0; x < 100 ; x ++){

                                            System.out.println(Thread.currentThread().getName()+":"+x);

                                   }

                          }

                  }).start() ;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
牙科就诊管理系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的Mysql数据库进行程序开发。实现了用户在线查看数据。管理员管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等功能。牙科就诊管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 管理员在后台主要管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等。 牙医列表页面,此页面提供给管理员的功能有:查看牙医、新增牙医、修改牙医、删除牙医等。公告信息管理页面提供的功能操作有:新增公告,修改公告,删除公告操作。公告类型管理页面显示所有公告类型,在此页面既可以让管理员添加新的公告信息类型,也能对已有的公告类型信息执行编辑更新,失效的公告类型信息也能让管理员快速删除。药品管理页面,此页面提供给管理员的功能有:新增药品,修改药品,删除药品。药品类型管理页面,此页面提供给管理员的功能有:新增药品类型,修改药品类型,删除药品类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值