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

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. public DieLock(boolean flag) {
  11. this.flag = flag;
  12. }
  13.  
  14. @Override
  15. public void run() {
  16. if(flag) {
  17. synchronized(MyLock.objA) {
  18. System.out.println("if objA");//情况是当dl1走到这里等待锁B
  19. synchronized(MyLock.objB) {
  20. System.out.println("if objB");
  21. }
  22. }
  23. }else {
  24. synchronized(MyLock.objB) {
  25. System.out.println("else objB");//当dl2走到这里等待锁A
  26. synchronized(MyLock.objA) {
  27. System.out.println("else objA");
  28. }
  29. }
  30. }
  31. }
  32.  
  33. }

编写测试类:

  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) { if(x%2==0) {
  18. s.name = "王友虎";
  19. s.age = 22;
  20. }else {
  21. s.name = "李智恩";
  22. s.age = 20;
  23. } x++;
  24. }
  25.  
  26. }
  27.  
  28. }

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) { System.out.println(s.name+"---"+s.age); }
  17.  
  18. }
  19.  
  20. }

测试类:

  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. }

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. public synchronized void set(String name,int age) {
  17. if(flag) {
  18. try {
  19. this.wait();
  20. } catch (InterruptedException e) {
  21. e.printStackTrace();
  22. }
  23. }
  24.  
  25. this.name = name;
  26. this.age = age;
  27.  
  28. //修改
  29. flag = true;
  30.  
  31. //唤醒
  32. this.notify();
  33. }
  34.  
  35. public synchronized void get() {
  36. if(!flag) {
  37. try {
  38. this.wait();
  39. } catch (InterruptedException e) {
  40. e.printStackTrace();
  41. }
  42. }
  43.  
  44. System.out.println(this.name + "---" + this.age);
  45.  
  46. //修改
  47. flag = false;
  48.  
  49. //唤醒
  50. this.notify();
  51. }
  52.  
  53. }

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. }

测试类:

  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. System.out.println(t1.getThreadGroup().getName());
  17. System.out.println(tg.getName());
  18. }
  19.  
  20. }

  (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. @Override
  17. public Integer call() throws Exception {
  18. int sum =0;
  19. for(int x = 1;x<=number;x++) {
  20. sum += x;
  21. // System.out.println(Thread.currentThread().getName()+":"+sum);
  22. }
  23. // System.out.println(Thread.currentThread().getName()+":"+sum);
  24. return sum;
  25. }
  26.  
  27. }

测试类:

  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. System.out.println(i1);
  29. System.out.println(i2);
  30. System.out.println(i3);
  31.  
  32. pool.shutdown();
  33. }
  34.  
  35. }

  (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. }

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. }

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. }

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

  (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. */

大数据之路week03--day05(线程 II)的更多相关文章

  1. 大数据之路week03--day05(线程 I)

    真的,身体这个东西一定要爱护好,难受的时候电脑都不想去碰,尤其是胃和肾... 这两天耽误了太多时间,今天好转了立刻学习,即刻不能耽误!. 话不多说,说正事: 1.多线程(理解) (1)多线程:一个应用 ...

  2. 大数据之路week01--自学之集合_1(Collection)

    经过我个人的调查,发现,在今后的大数据道路上,集合.线程.网络编程变得尤为重要,为什么? 因为大数据大数据,我们必然要对数据进行处理,而这些数据往往是以集合形式存放,掌握对集合的操作非常重要. 在学习 ...

  3. 大数据之路week07--day03(Hadoop深入理解,JAVA代码编写WordCount程序,以及扩展升级)

    什么是MapReduce 你想数出一摞牌中有多少张黑桃.直观方式是一张一张检查并且数出有多少张是黑桃. MapReduce方法则是: 1.给在座的所有玩家中分配这摞牌 2.让每个玩家数自己手中的牌有几 ...

  4. 大数据之路week04--day06(I/O流阶段一 之异常)

    从这节开始,进入对I/O流的系统学习,I/O流在往后大数据的学习道路上尤为重要!!!极为重要,必须要提起重视,它与集合,多线程,网络编程,可以说在往后学习或者是工作上,起到一个基石的作用,没了地基,房 ...

  5. 大数据之路week04--day03(网络编程)

    哎,怎么感觉自己变得懒了起来,更新博客的频率变得慢了起来,可能是因为最近得知识开始变得杂变得难了起来,之前在上课的时候,也没有好好听这一方面的知识,所以,现在可以说是在学的新的知识,要先去把新的知识思 ...

  6. C#码农的大数据之路 - 使用C#编写MR作业

    系列目录 写在前面 从Hadoop出现至今,大数据几乎就是Java平台专属一般.虽然Hadoop或Spark也提供了接口可以与其他语言一起使用,但作为基于JVM运行的框架,Java系语言有着天生优势. ...

  7. 胖子哥的大数据之路(11)-我看Intel&&Cloudera的合作

    一.引言 5月8日,作为受邀嘉宾,参加了Intel与Cloudera在北京中国大饭店新闻发布会,两家公司宣布战略合作,该消息成为继Intel宣布放弃大数据平台之后的另外一个热点新闻.对于Intel的放 ...

  8. 胖子哥的大数据之路(10)- 基于Hive构建数据仓库实例

    一.引言 基于Hive+Hadoop模式构建数据仓库,是大数据时代的一个不错的选择,本文以郑商所每日交易行情数据为案例,探讨数据Hive数据导入的操作实例. 二.源数据-每日行情数据 三.建表脚本 C ...

  9. 胖子哥的大数据之路(9)-数据仓库金融行业数据逻辑模型FS-LDM

    引言: 大数据不是海市蜃楼,万丈高楼平地起只是意淫,大数据发展还要从点滴做起,基于大数据构建国家级.行业级数据中心的项目会越来越多,大数据只是技术,而非解决方案,同样面临数据组织模式,数据逻辑模式的问 ...

随机推荐

  1. 移动架构-json解析框架

    JSON在现在数据传输中占据着重要地位,相比于xml,其解析和构成都要简单很多,第三方的解析框架也不胜枚举,这里之所以要自定义一个json解析框架,一方面是更好的了解json解析过程,另一方面是有时候 ...

  2. VBA实现打开Excel文件读取内容拷贝Format且加超链接

    '-------------------一覧取得----------------------------- Sub getRedmineGrid_Click() Dim wb As Workbook ...

  3. Java线程安全队列Queue实现原理

    原文链接:https://www.cnblogs.com/DreamRecorder/p/9223016.html 在Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列.J ...

  4. Redis服务监控之RedisLive安装部署(亲测可用)

    一.Redis服务安装部署 1.redis安装(linux系统) 下载 https://redis.io/ 安装依赖 yum install gcc tcl 解压.编译.安装(make & m ...

  5. Hystrix(下),使用公共降级类

    使用Hystrix熔断(下) 在一个分布式系统里,一个服务依赖多个服务,可能存在某个服务调用失败,         比如超时.异常等,如何能够保证在一个依赖出问题的情况下,不会导致整体服务失败,   ...

  6. 1234: 约瑟夫问题-输出最后的编号(Java)

    WUSTOJ 1234: 约瑟夫问题-输出最后的编号 参考资料 约瑟夫问题--百度百科 Description n个人围成一圈,依次从1至n编号.从编号为1的人开始1至k报数,凡报数为k的人退出圈子, ...

  7. java异常那些事

    异常的基本定义: 异常情形是指阻止当前方法或者作用域继续执行的问题.在这里一定要明确一点:异常代码某种程度的错误,尽管Java有异常处理机制,但是我们不能以“正常”的眼光来看待异常,异常处理机制的原因 ...

  8. oracle 数据库 主键索引重建

    oracle 数据库 主键索引重建 alter table table_name drop primary key; alter table table_name add constraint pk_ ...

  9. Linux Mysql 备份与还原

    1. 备份 cd /var/lib/mysql //进入到MySQL库目录 mysqldump -u root -p 数据库>/root/backup/数据库.sql 然后输入密码 2. 还原 ...

  10. Nginx安装配置|Nginx反向代理|Nginx支持HTTPS|Nginx重定向

    Nginx安装配置 可以直接看到最下面的HTTPS. Nginx安装 我的系统如下: No LSB modules are available. Distributor ID: Ubuntu Desc ...