zoukankan      html  css  js  c++  java
  • 大数据之路week03--day05(线程 II)

    今天,咱们就把线程给完完全全的结束掉,但是不是说,就已经覆盖了全部的知识点,可以说是线程的常见的问题及所含知识基本都包含。

    1、多线程(理解)

      (1)JDK5以后的针对线程的锁定操作和释放操作

        Lock锁

      (2)死锁问题的描述和代码体现

        同步的弊端:

          A:效率低

          B:容易产生死锁

        死锁:

          两个或两个以上的线程在争夺资源的过程中,发生的一种相互等待现象。

        举例:

          中国人和外国人吃饭的案例

          正常情况下:

            中国人:筷子两支

            外国人:刀和叉

          死锁情况下:

            中国人:筷子1支,刀一把。

            外国人:筷子1支,叉一把。

            (都在等待对方给自己的用具)

    用代码怎么体现一个死锁问题?(面试题

    创建一个锁类,有两把锁:

     1 package com.wyh.lock;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 上午8:27:03
     6 */
     7 public class MyLock {
     8     
     9     //定义两把锁
    10     public static final Object objA = new Object();
    11     public static final Object objB = new Object();
    12 
    13 }

    创建线程类,重写run方法:

     1 package com.wyh.lock;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 上午8:28:17
     6 */
     7 public class DieLock extends Thread{
     8     private boolean flag;
     9     
    10     
    11     public DieLock(boolean flag) {
    12         this.flag = flag;
    13     }
    14 
    15     @Override
    16     public void run() {
    17         if(flag) {
    18             synchronized(MyLock.objA) {
    19                 System.out.println("if objA");//情况是当dl1走到这里等待锁B
    20                 synchronized(MyLock.objB) {
    21                     System.out.println("if objB");
    22                 }
    23             }
    24         }else {
    25             synchronized(MyLock.objB) {
    26                 System.out.println("else objB");//当dl2走到这里等待锁A
    27                 synchronized(MyLock.objA) {
    28                     System.out.println("else objA");
    29                 }
    30             }
    31         }
    32     }
    33     
    34 }

    编写测试类:

     1 package com.wyh.lock;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 上午8:33:50
     6 */
     7 public class DieLockDemo {
     8     public static void main(String[] args) {
     9         DieLock dl1 = new DieLock(true);
    10         DieLock dl2 = new DieLock(false);
    11         
    12         dl1.start();
    13         dl2.start();
    14     }
    15 
    16 }

      (3)生产者和消费者多线程体现(线程间的通信问题)

        上一节我们写的售票程序并不符合实际情况。

          以学生作为资源来实现的

          资源类:student

          设置数据类:SetThread(生产者)

          获取数据类:GetThread(消费者)

          测试类:StudentDemo

          代码:

    A:最基本的版本,只有一个数据。

    Student类:

     1 package 生产者消费者01;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 上午9:03:02
     6 */
     7 public class Student {
     8     String name;
     9     int age;
    10 
    11 }

    SetThread类:(为了保证多个线程是操作同一个学生,我们重写有参构造方法)

     1 package 生产者消费者01;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 上午9:03:35
     6 */
     7 public class StudentSetThread implements Runnable {
     8     private Student s ;
     9     
    10     public StudentSetThread(Student s) {
    11         this.s = s;
    12     }
    13 
    14     @Override
    15     public void run() {
    16         s.name = "王友虎";
    17         s.age = 22;
    18     }
    19 
    20 }

    SetThread类:

     1 package 生产者消费者01;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 上午9:04:46
     6 */
     7 public class StudentGetThread implements Runnable {
     8     private Student s ;
     9     
    10     public StudentGetThread(Student s) {
    11         this.s = s;
    12     }
    13 
    14     @Override
    15     public void run() {
    16         System.out.println(s.name+"---"+s.age);
    17     }
    18 
    19 }

    测试类;

     1 package 生产者消费者01;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 上午9:05:35
     6 */
     7 public class StudentThreadDemo {
     8     public static void main(String[] args) {
     9         Student s = new Student();
    10         StudentSetThread st = new StudentSetThread(s);
    11         StudentGetThread sg = new StudentGetThread(s);
    12         
    13         Thread t1 = new Thread(st);
    14         Thread t2 = new Thread(sg);
    15         
    16         t2.start();
    17         t1.start();
    18         
    19     }
    20 }

    但是运行多次我们发现,有出现姓名为null或者年龄为0的情况出现,这是为什么?

     这是因为CPU进行的操作都是原子操作,有情况是当对年龄进行赋值,还没来得及对姓名赋值,下一个线程就进行输出。从而导致有null的情况,其他情况类推。

    B:改进版本,给出了不同的数据。并加入了同步机制。

    为了数据效果好一点,我们设置循环和判断,给出不同的值.

    学生类:

     1 package 生产者消费者02;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 上午9:03:02
     6 */
     7 public class Student {
     8     String name;
     9     int age;
    10 
    11 }

    SetThread类:

     1 package 生产者消费者02;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 上午9:03:35
     6 */
     7 public class StudentSetThread implements Runnable {
     8     private Student s ;
     9     private int x = 0;
    10     
    11     public StudentSetThread(Student s) {
    12         this.s = s;
    13     }
    14 
    15     @Override
    16     public void run() {
    17         while(true) {19                 if(x%2==0) {
    20                     s.name = "王友虎";
    21                     s.age = 22;
    22                 }else {
    23                     s.name = "李智恩";
    24                     s.age = 20;
    25                 }27             x++;
    28         }
    29         
    30     }
    31 
    32 }

    GetThread类:

     1 package 生产者消费者02;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 上午9:04:46
     6 */
     7 public class StudentGetThread implements Runnable {
     8     private Student s ;
     9     
    10     public StudentGetThread(Student s) {
    11         this.s = s;
    12     }
    13 
    14     @Override
    15     public void run() {
    16         while(true) {18                 System.out.println(s.name+"---"+s.age);20         }
    21         
    22     }
    23 
    24 }

    测试类:

     1 package 生产者消费者02;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 上午9:05:35
     6 * 
     7 * 解决线程安全的问题
     8 * 
     9 */
    10 public class StudentThreadDemo {
    11     public static void main(String[] args) {
    12         Student s = new Student();
    13         StudentSetThread st = new StudentSetThread(s);
    14         StudentGetThread sg = new StudentGetThread(s);
    15         
    16         Thread t1 = new Thread(st);
    17         Thread t2 = new Thread(sg);
    18         
    19         t2.start();
    20         t1.start();
    21         
    22     }
    23 }

    运行结果:

     我们发现了问题

        1:同一个数据出现多次

            CPU的一点点时间片的执行权,就足够执行很多次

        2:姓名和年龄不匹配

            线程运行的随机性

    很显然,我们这个改进还是存在线程安全的问题:

      怎么判断一个线程是不是安全的:

        1:是否是多线程环境  是

        2:是都有共享数据  是

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

    C:等待唤醒机制改进程序。让数据能够实现依次的出现

                wait()  :等待

                notify(): 唤醒单个线程

                notifyAll(): 唤醒多个线程

    (上面这3个方法的调用必须是通过锁对象调用,而当我们使用的锁悐是任意锁,所以和没加锁区别不大,所以,这些方法必须定义在Object类中s)

    对上面的进行解决:加锁,synchronized,并且通过等待唤醒机制进行操作。保证数据是依次出现的

    注意:1、不同种类的线程都要加锁。   2、不同种类的线程加的锁必须是同一把。

    学生类:

     1 package 生产者消费者03;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 上午9:03:02
     6 */
     7 public class Student {
     8     String name;
     9     int age;
    10     boolean flag; //默认没有数据.false
    11 }

    SetThread类:

     1 package 生产者消费者03;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 上午9:03:35
     6 */
     7 public class StudentSetThread implements Runnable {
     8     private Student s ;
     9     private int x = 0;
    10     
    11     public StudentSetThread(Student s) {
    12         this.s = s;
    13     }
    14 
    15     @Override
    16     public void run() {
    17         while(true) {
    18             synchronized(s) {
    19                 if(s.flag) {
    20                     try {
    21                         s.wait();
    22                     } catch (InterruptedException e) {
    23                         e.printStackTrace();
    24                     }
    25                 }
    26                 
    27                 if(x%2==0) {
    28                     s.name = "王友虎";
    29                     s.age = 22;
    30                 }else {
    31                     s.name = "李智恩";
    32                     s.age = 20;
    33                 }
    34                 
    35                 //此时有数据
    36                 s.flag = true;
    37                 //唤醒线程
    38                 s.notify(); //唤醒不代表立即执行,还需要争夺CPU执行权.
    39                 
    40             }  
    41             x++;
    42             
    43             
    44             
    45         }
    46         
    47     }
    48 
    49 }

    GetThread类:

     1 package 生产者消费者03;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 上午9:04:46
     6 */
     7 public class StudentGetThread implements Runnable {
     8     private Student s ;
     9     
    10     public StudentGetThread(Student s) {
    11         this.s = s;
    12     }
    13 
    14     @Override
    15     public void run() {
    16         while(true) {
    17             synchronized (s) {
    18                 if(!s.flag) {
    19                     try {
    20                         s.wait();
    21                     } catch (InterruptedException e) {
    22                         e.printStackTrace();
    23                     }
    24                 }
    25                 System.out.println(s.name+"---"+s.age);
    26                 
    27                 //消費了
    28                 s.flag = false;
    29                 //綫程
    30                 s.notify();
    31                 
    32             }
    33         }
    34         
    35     }
    36 
    37 }

    测试类:

     1 package 生产者消费者03;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 上午9:05:35
     6 * 
     7 * 等待唤醒机制
     8 * 
     9 */
    10 public class StudentThreadDemo {
    11     public static void main(String[] args) {
    12         Student s = new Student();
    13         StudentSetThread st = new StudentSetThread(s);
    14         StudentGetThread sg = new StudentGetThread(s);
    15         
    16         Thread t1 = new Thread(st);
    17         Thread t2 = new Thread(sg);
    18         
    19         t2.start();
    20         t1.start();
    21         
    22     }
    23 }

    D:资源唤醒机制的代码优化,

    把数据及操作都写在了资源类中,同步方法实现。

    学生类:

     1 package 生产者消费者04优化;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 上午9:03:02
     6 * 
     7 * 
     8 * 用同步方法来优化
     9 * 
    10 */
    11 public class Student {
    12     private String name;
    13     private int age;
    14     private boolean flag; //默认没有数据.false
    15     
    16     
    17     public synchronized void set(String name,int age) {
    18         if(flag) {
    19             try {
    20                 this.wait();
    21             } catch (InterruptedException e) {
    22                 e.printStackTrace();
    23             }
    24         }
    25         
    26         this.name = name;
    27         this.age = age;
    28         
    29         //修改
    30         flag = true;
    31         
    32         //唤醒
    33         this.notify(); 
    34     }
    35     
    36     
    37     public synchronized void get() {
    38         if(!flag) {
    39             try {
    40                 this.wait();
    41             } catch (InterruptedException e) {
    42                 e.printStackTrace();
    43             }
    44         }
    45         
    46         System.out.println(this.name + "---" + this.age);
    47         
    48         //修改
    49         flag = false;
    50         
    51         //唤醒
    52         this.notify();
    53     }
    54     
    55     
    56     
    57 }

    SetThread类:

     1 package 生产者消费者04优化;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 上午9:03:35
     6 */
     7 public class StudentSetThread implements Runnable {
     8     private Student s ;
     9     private int x = 0;
    10     
    11     public StudentSetThread(Student s) {
    12         this.s = s;
    13     }
    14 
    15     @Override
    16     public void run() {
    17         while(true) {
    18                 if(x%2==0) {
    19                     s.set("王友虎", 22);
    20                 }else {
    21                     s.set("李智恩", 20);
    22                 } 
    23                 x++; 
    24             }    
    25         }
    26 
    27 }

    GetThread类:

     1 package 生产者消费者04优化;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 上午9:04:46
     6 */
     7 public class StudentGetThread implements Runnable {
     8     private Student s ;
     9     
    10     public StudentGetThread(Student s) {
    11         this.s = s;
    12     }
    13 
    14     @Override
    15     public void run() {
    16         while(true) {
    17                 s.get();
    18                 
    19             }
    20         }
    21         
    22     }

    测试类:

     1 package 生产者消费者04优化;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 上午9:05:35
     6 * 
     7 * 等待唤醒机制
     8 * 
     9 */
    10 public class StudentThreadDemo {
    11     public static void main(String[] args) {
    12         Student s = new Student();
    13         StudentSetThread st = new StudentSetThread(s);
    14         StudentGetThread sg = new StudentGetThread(s);
    15         
    16         Thread t1 = new Thread(st);
    17         Thread t2 = new Thread(sg);
    18         
    19         t2.start();
    20         t1.start();
    21         
    22     }
    23 }

    线程的状态转换图:

      

      (4)线程组(用实现Runnable接口的方式举例)

     1 package 线程组1;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 上午10:30:51
     6 */
     7 public class MyRunnable implements Runnable{
     8 
     9     @Override
    10     public void run() {
    11         System.out.println(Thread.currentThread().getName());
    12         
    13         
    14     }
    15     
    16 }

    测试类:

     1 package 线程组1;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 上午10:31:37
     6 */
     7 public class MyRunnableDemo {
     8     public static void main(String[] args) {
     9         ThreadGroup tg = new ThreadGroup("这是一个新的线程组");
    10         
    11         MyRunnable mr = new MyRunnable();
    12         
    13         Thread t1 = new Thread(tg,mr,"王友虎");
    14         Thread t2 = new Thread(tg,mr,"李智恩");
    15         
    16         
    17         System.out.println(t1.getThreadGroup().getName());
    18         System.out.println(tg.getName());
    19     }
    20 
    21 }

      (5)线程池

        程序启动一个新的线程成本是比较高的,因为它涉及到要与操作系统进行交互,而使用线程池可以很好的提高性能,尤其是当程序中要创建大量生存期很短的线程时,更应该考虑使用线程池。

          1、线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。

          2、在JDK5之前,我们必须手动实现自己的线程池,从JDk5开始,Java内置支持线程池。

        如何实现线程池的代码呢?

          1、创建一个线程对象,控制要创建几个线程对象。

            public static ExecutorService newFixedThreadPool(int nThread)

          2、这种线程池的线程可以执行:

            可以执行Runnable对象或者Callable对象代表的线程

            做一个类实现Runnable接口。

          3、调用下面的方法即可

            Future submit(Runnable task)

            <T> future<T> submit(Callable<T> task)

          4、我就要结束,可以吗? 可以。

            shutdown()

    实现Runnable接口:

     1 package 线程池;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 上午11:08:38
     6 */
     7 public class MyRunnable implements Runnable{
     8 
     9     @Override
    10     public void run() {
    11         for(int x = 0;x<500;x++) {
    12             System.out.println(Thread.currentThread().getName()+":"+x);
    13         }
    14         
    15     }
    16 
    17 }

    测试类:

     1 package 线程池;
     2 
     3 import java.util.concurrent.Executor;
     4 import java.util.concurrent.ExecutorService;
     5 import java.util.concurrent.Executors;
     6 
     7 /** 
     8 * @author WYH
     9 * @version 2019年11月23日 上午11:09:57
    10 * 
    11 * 线程池的创建
    12 */
    13 public class ExecutorsDemo {
    14     public static void main(String[] args) {
    15         //创建线程池
    16         ExecutorService pool = Executors.newFixedThreadPool(2);
    17         ExecutorService pool1 = Executors.newCachedThreadPool();
    18         
    19         pool.submit(new MyRunnable());
    20         pool.submit(new MyRunnable());
    21         
    22         pool1.submit(new MyRunnable());
    23         pool1.submit(new MyRunnable());
    24         pool1.submit(new MyRunnable());
    25         
    26         pool.shutdown();
    27         pool1.shutdown();
    28         
    29     }
    30 
    31 }

      (6)多线程实现的第三种方案

    MyCallable类:

     1 package com.wyh.callable;
     2 
     3 import java.util.concurrent.Callable;
     4 
     5 /** 
     6 * @author WYH
     7 * @version 2019年11月23日 下午2:29:25
     8 */
     9 public class MyCallable implements Callable {
    10 
    11     @Override
    12     public Object call() throws Exception {
    13         for(int x = 0;x<500;x++) {
    14             System.out.println(Thread.currentThread().getName()+":"+x);
    15         }
    16         return null;
    17     }
    18 
    19 }

    测试类:

     1 package com.wyh.callable;
     2 
     3 import java.util.concurrent.ExecutorService;
     4 import java.util.concurrent.Executors;
     5 
     6 /** 
     7 * @author WYH
     8 * @version 2019年11月23日 下午2:30:21
     9 * 
    10 * 创建线程的第三种方式
    11 */
    12 public class MyCallableDemo {
    13     public static void main(String[] args) {
    14         //创建线程池
    15         ExecutorService pool = Executors.newFixedThreadPool(2);
    16         
    17         pool.submit(new MyCallable());
    18         pool.submit(new MyCallable());
    19         
    20         pool.shutdown();
    21     }
    22 
    23 }

      (6_2)Callable的案例(计算1+....的总和 线程池实现)

    Runnable类:

     1 package com.wyh.callable案例1;
     2 
     3 import java.util.concurrent.Callable;
     4 
     5 /** 
     6 * @author WYH
     7 * @version 2019年11月23日 下午2:29:25
     8 */
     9 public class MyCallable implements Callable<Integer> {
    10     private int number;
    11     
    12     public MyCallable(int number) {
    13         this.number = number;
    14     }
    15     
    16 
    17     @Override
    18     public Integer call() throws Exception {
    19         int sum =0;
    20         for(int x = 1;x<=number;x++) {
    21             sum += x;
    22 //            System.out.println(Thread.currentThread().getName()+":"+sum);
    23         }
    24 //        System.out.println(Thread.currentThread().getName()+":"+sum);
    25         return sum;
    26     }
    27 
    28 }

    测试类:

     1 package com.wyh.callable案例1;
     2 
     3 import java.beans.FeatureDescriptor;
     4 import java.util.concurrent.ExecutionException;
     5 import java.util.concurrent.ExecutorService;
     6 import java.util.concurrent.Executors;
     7 import java.util.concurrent.Future;
     8 
     9 /** 
    10 * @author WYH
    11 * @version 2019年11月23日 下午2:30:21
    12 * 
    13 * 创建线程的第三种方式
    14 */
    15 public class MyCallableDemo {
    16     public static void main(String[] args) throws InterruptedException, ExecutionException {
    17         //创建线程池
    18         ExecutorService pool = Executors.newFixedThreadPool(3);
    19         
    20         Future<Integer> f1 = pool.submit(new MyCallable(50));
    21         Future<Integer> f2 = pool.submit(new MyCallable(100));
    22         Future<Integer> f3 = pool.submit(new MyCallable(200));
    23         
    24         int i1 = f1.get();
    25         int i2 = f2.get();
    26         int i3 = f3.get();
    27                 
    28         
    29         System.out.println(i1);
    30         System.out.println(i2);
    31         System.out.println(i3);
    32         
    33         
    34         pool.shutdown();
    35     }
    36 
    37 }

      (7)多线程的面试题

        a:多线程有几种实现方案,分别是哪几种?

          两种。(面试答2种

            继承Thread类

            实现Runnable接口

            扩展一种,实现Callable接口,这个要和线程池结合使用。

        b:同步有几种方式,分别是是什么?

          两种。

            同步代码块  锁是任意对象锁

            同步方法   锁是this

            同步静态方法  锁是当前类的二进制字节码文件

        c:启动一个线程是run()还是start()?它们的区别?

          start()

            run():封装了被线程执行的代码块,直接调用仅仅是一个普通方法的调用

            start():启动线程,并由JVM自动调用run()方法

        d:sleep()和wait()方法的区别

          sleep():必须指定时间,不释放锁。

          wait():可以不指定时间,也可以指定时间,但是它释放锁。

        e:为什么wait(), notify(), notifyAll()等方法都定义在Object类中?

          因为这些方法的调用是依赖于锁对象的,而同步代码块的锁对象是任意锁。而Object代表任意对象,所以,定义在里面。

        f:线程的生命周期图(如上)

          新建 -- 就绪 -- 运行 -- 死亡

          新建 -- 就绪 -- 运行 -- 阻塞 -- 就绪 -- 运行 -- 死亡

    2、设计模式(理解)

      (1)面试对象的常见设计原则

          单一职责原则

          开闭原则

          里氏替换原则

          依赖注入原则

          接口分离原则

          迪米特原则

      (2)设计模式概述和分类

        A:经验的总结

        B:三类:

          创建型

          结构型

          行为型

      (3)改进的设计模式

        A:简单工厂模式

     Animal类:

     1 package 工厂设计模式;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 下午4:36:06
     6 */
     7 public abstract class Animal {
     8     public abstract void eat();
     9 
    10 }
    Animal
     1 package 工厂设计模式;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 下午4:37:44
     6 */
     7 public class AnimalFactory {
     8     private AnimalFactory(){
     9         
    10     }
    11     
    12     public static Animal CreateAnimal(String type) {
    13         if(type.equals("dog")) {
    14             return new Dog();
    15         }else if(type.equals("cat")) {
    16             return new Cat();
    17         }else {
    18             return null;
    19         }
    20     }
    21 
    22 }
    AnimalFactory
     1 package 工厂设计模式;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 下午4:37:16
     6 */
     7 public class Cat extends Animal {
     8 
     9     @Override
    10     public void eat() {
    11         System.out.println("猫吃鱼");
    12 
    13     }
    14 
    15 }
    Cat
     1 package 工厂设计模式;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 下午4:36:45
     6 */
     7 public class Dog extends Animal {
     8 
     9     @Override
    10     public void eat() {
    11         System.out.println("狗吃肉");
    12         
    13 
    14     }
    15 
    16 }
    Dog
     1 package 工厂设计模式;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 下午4:41:54
     6 */
     7 public class FactoryDemo {
     8     public static void main(String[] args) {
     9         Animal a = AnimalFactory.CreateAnimal("dog");
    10         a.eat();
    11         Animal b = AnimalFactory.CreateAnimal("cat");
    12         b.eat();
    13         
    14         Animal c = AnimalFactory.CreateAnimal("pig");
    15         if(c != null) {
    16             c.eat();
    17         }else {
    18             System.out.println("对不起,该工厂无法造该对象.");
    19         }
    20         
    21         
    22         
    23     }
    24 
    25 }
    FactoryDemo

        B:工厂方法模式

     1 package 工厂方法模式;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 下午5:18:40
     6 */
     7 public abstract class Animal {
     8     public abstract void eat();
     9 
    10 }
    Animal
     1 package 工厂方法模式;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 下午5:19:23
     6 */
     7 public interface Factory {
     8     public abstract Animal CreateAnimal();
     9 
    10 }
    Factory
     1 package 工厂方法模式;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 下午5:20:39
     6 */
     7 public class Dog extends Animal {
     8 
     9     @Override
    10     public void eat() {
    11         System.out.println("狗吃肉");
    12 
    13     }
    14 
    15 }
    Dog
     1 package 工厂方法模式;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 下午5:22:01
     6 */
     7 public class DogFactory implements Factory {
     8 
     9     @Override
    10     public Animal CreateAnimal() {
    11         return new Dog();
    12     }
    13 
    14 }
    DogFactory
     1 package 工厂设计模式;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 下午4:37:16
     6 */
     7 public class Cat extends Animal {
     8 
     9     @Override
    10     public void eat() {
    11         System.out.println("猫吃鱼");
    12 
    13     }
    14 
    15 }
    Cat
     1 package 工厂方法模式;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 下午5:23:46
     6 */
     7 public class CatFactory implements Factory {
     8 
     9     @Override
    10     public Animal CreateAnimal() {
    11         return new Cat();
    12     }
    13 
    14 }
    CatFactory
     1 package 工厂方法模式;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 下午5:20:03
     6 */
     7 public class FactoryDemo {
     8     public static void main(String[] args) {
     9         //我需要狗
    10         Factory f = new DogFactory();
    11         Animal a = f.CreateAnimal();
    12         a.eat();
    13         
    14         //我需要猫
    15         f = new CatFactory();
    16         Animal a1 = f.CreateAnimal();
    17         a1.eat();
    18         
    19     }
    20 
    21 }
    FactoryDemo

        C:单例模式(掌握)

            a:饿汉式

    Student类:

     1 package 单例模式;
     2 
     3 /**
     4  * @author WYH
     5  * @version 2019年11月23日 下午6:20:40
     6  */
     7 public class Student {
     8     // 将构造方法私有
     9     private Student() {
    10 
    11     }
    12 
    13     // 自己创建一个对象
    14     // 静态方法只能访问静态的成员变量,加static
    15     // 为了不让外界随意改动这个对象,我们将他私有化
    16     private static Student s = new Student();
    17 
    18     // 提供一个方法给外界进行访问到这个对象
    19     public static Student getStudent() {
    20         return s;
    21     }
    22 
    23 }

    测试类:

     1 package 单例模式;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 下午6:20:47
     6 * 
     7 * 单例模式:保证类在内存中指存在一个对象
     8 * 饿汉式
     9 * 
    10 */
    11 public class StudentDemo1 {
    12     public static void main(String[] args) {
    13         
    14         Student s1 = Student.getStudent();
    15         Student s2 = Student.getStudent();
    16         
    17         System.out.println(s1 == s2);
    18     }
    19 
    20 }

            b:懒汉式

    Teacher类:

     1 package 单例模式;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 下午6:32:09
     6 * 
     7 * 懒汉式
     8 */
     9 public class Teacher {
    10     private Teacher() {
    11         
    12     }
    13     
    14     private static Teacher teacher = null;
    15     
    16     public synchronized static Teacher getTeacher() {
    17         if(teacher == null) {
    18             teacher = new Teacher();
    19         }
    20         
    21         return teacher;
    22     }
    23 
    24 }

    测试类:

     1 package 单例模式;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月23日 下午6:34:12
     6 */
     7 public class TeacherDemo {
     8     public static void main(String[] args) {
     9         Teacher t1 = Teacher.getTeacher();
    10         Teacher t2 = Teacher.getTeacher();
    11         
    12         System.out.println(t1 == t2);
    13         System.out.println(t1);
    14         System.out.println(t2);
    15         
    16         
    17     }
    18 
    19 }

    (注意:面试的时候写懒汉式,开发的时候写饿汉式,因为饿汉式不存在线程安全问题)

      (4)Runtime

          JDK提供的一个单例模式应用的类

          还可以通过dos命令。

    例子:

     1 package 单例模式;
     2 
     3 import java.io.IOException;
     4 
     5 /** 
     6 * @author WYH
     7 * @version 2019年11月23日 下午6:43:36
     8 * 
     9 * 饿汉式的一个类的例子
    10 * 
    11 * 
    12 */
    13 public class RunTimeDemo {
    14     public static void main(String[] args) throws IOException {
    15         Runtime r = Runtime.getRuntime();
    16 //        r.exec("calc"); //调出计算器
    17 //        r.exec("shutdown -s -t 10000");
    18         r.exec("shutdown -a");
    19     }
    20 }
    21 
    22 /*
    23  * 源码:
    24  * 
    25  * class Runtime{
    26  *      private Runtime() {}
    27  *      private static Runtime currentRuntime = new Runtime();
    28  *      public static Runtime getRuntime() {
    29  *               return currentRuntime;
    30  *      }
    31  * 
    32  * }
    33  */
  • 相关阅读:
    vue : 无法加载文件 C:UsersXXXAppDataRoaming pmvue.ps1,因为在此系统上禁止运行脚本
    js全屏和退出全屏浏览器
    js 如何保存代码段并执行以及动态加载script
    计算年龄,精确到年月日
    js闭包问题
    构造函数和继承方法
    js 箭头函数不适用的场景
    获取一组数据的最大值和最小值
    地图
    json传输
  • 原文地址:https://www.cnblogs.com/wyh-study/p/11920653.html
Copyright © 2011-2022 走看看