• Java基础8-多线程;同步代码块


    作业解析

    1. 利用白富美接口案例,土豪征婚使用匿名内部类对象实现。

       interface White{
           public void white();
       }
      
       interface Rich{
           public void rich();
       }
      
       interface Beauty{
           public void beauty();
       }
      
       interface WRB extends White, Rich, Beauty{
       }
      
       class TuHao{
           public void getMarry(WRB wrb){
               wrb.white();
               wrb.rich();
               wrb.beauty();
           }
       }
      
       class Demo{
           public static void main(String[] args){
               TuHao wsc = new TuHao();
               wsc.getMarry(new WRB(){
                   public void white(){
                       System.out.println("white");
                   }
                   public void rich(){
                       System.out.println("rich");
                   }
                   public void beauty(){
                       System.out.println("beauty");
                   }    
               });
           }
       }
      
      
    2. 定义三角形类Trianle,里面包含三个int类型属性,分别表示三条边的长度,
      构造三角形对象时,任意两边之和是否大于第三边,如若不成立,抛出自定义异常。

       class Triangle{
           private int a;
           private int b;
           private int c;
           public Triangle(int a, int b, int c){
               try{
                   if(a>=b+c || b>=a+c || c>=a+b){
                       throw new TriangleLengthException("Invalid Length");
                   }
                   else{
                       this.a = a;
                       this.b = b;
                       this.c = c;
                   }
               }
               catch(TriangleLengthException e){
                   e.printStackTrace();
               }
           }
       }
      
       class TriangleLengthException extends Exception{
           String exceptionInfo;
           public TriangleLengthException(String info){
               exceptionInfo = info;
           }
      
           public void printStackTrace(){
               System.out.println(exceptionInfo);
           }
       }
      
       class TriExceptionDemo{
           public static void main(String[] args){
               Triangle t1 = new Triangle(2,3,4);
               Triangle t2 = new Triangle(2,2,4);
               Triangle t3 = new Triangle(2,7,4);
           }
       }
      
      
    3. Person类中增加birthday属性,对setBirthday(int ,int , int )方法进行异常处理,
      要求年有效、月有效、日有效、年月日指定的具体日期有效,对不同情况分别抛出不同的异常。
      year:>1970, month:1-12, day:1-31

       class Person{
           private int year;
           private int month;
           private int day;
           public void setBirthday(int year, int month, int day){
               try{
                   if(year<1970){
                       throw new YearException("Invalid Year");
                   }
                   else{
                       if(month<1 || month > 12){
                           throw new MonthException("Invalid Month");
                       }
                       else{
                           if(day<1 || day>31){
                               throw new DayException("Invalid Day");
                           }
                           else{
                               switch(month){
                                   case 1:
                                   case 3:
                                   case 5:
                                   case 7:
                                   case 8:
                                   case 10:
                                   case 12:
                                       break;
                                   case 2:
                                       if((year%400==0) || (year%4==0 && year%100!=0)){
                                           if(day>29){
                                               throw new DateException("Invalid Date");
                                           }
                                       }
                                       else{
                                           if(day>28){      
                                               throw new DateException("Invalid Date");
                                           }
                                       }
                                   case 4:
                                   case 6:
                                   case 9:
                                   case 11:
                                       if(day==31){
                                           throw new DateException("Invalid Date");
                                       }
                                   }
                               }
                           }
                       }
                   }
               catch(Exception e){
                   e.printStackTrace();
               }
           }
       }
      
       class YearException extends Exception{
           String exceptionInfo;
           public YearException(String info){
               exceptionInfo = info;
           }
           public void printStackTrace(){
               System.out.println(exceptionInfo);
           }
       }
      
       class MonthException extends Exception{
           String exceptionInfo;
           public MonthException(String info){
               exceptionInfo = info;
           }
           public void printStackTrace(){
               System.out.println(exceptionInfo);
           }
       }
      
       class DayException extends Exception{
           String exceptionInfo;
           public DayException(String info){
               exceptionInfo = info;
           }
           public void printStackTrace(){
               System.out.println(exceptionInfo);
           }
       }
      
       class DateException extends Exception{
           String exceptionInfo;
           public DateException(String info){
               exceptionInfo = info;
           }
           public void printStackTrace(){
               System.out.println(exceptionInfo);
           }
       }
      
       class BirthdayExceptionDemo{
           public static void main(String[] args){
           Person p1 = new Person();
           p1.setBirthday(12,1,22);
           p1.setBirthday(1970,13,22);
           p1.setBirthday(2000,1,32);
           p1.setBirthday(2000,2,28);
           p1.setBirthday(2000,2,29);
           p1.setBirthday(2016,2,30);
           p1.setBirthday(2100,2,29);
           }
       }
      
      
    4. 将类定义到指定的包下。com.xkzhai.jar,编译之后,打成jar文件。

      • 编写源文件jarDemo.java

          package com.xkzhai.jar;
          class Person{
              private String name;
              private String sex;
              public void run(){
                  System.out.println("run");
              }
          }
        
          class jarDemo{
              public static void main(String[] args){
                  Person p1 = new Person();
                  p1.run();
              }
          }
        
        
      • 编译到指定的位置

          javac -d classes2 jarDemo.java
        
        
      • 归档

          jar cvf test.jar -C classes2/ .
          jar cvfe test2.jar com.xkzhai.jar.jarDemo -C classes2/ . //在清单文件中增加入口点
        
        
      • 运行程序

          java -cp classes2 com.xkzhai.jar.jarDemo
          java -cp test.jar com.xkzhai.jar.jarDemo
          java -jar test2.jar//定义好入口点的jar包
        
        
    5. 相互之间使用jar包,放置cp下,对class进行重用

      • 编写第一个java程序Person.java

          package com.xkzhai.jar1;
          //不同包下的类重用,需定义为public
          public class Person{
              private String name;
              private String sex;
              private int age;
              public void setAge(int age){
                  this.age = age;
              }
              public int getAge(){
                  return age;
              }
          }
        
        
      • 编译上述文件,放置到classes3文件夹下

          javac -d classes3 Person.java
        
        
      • 将类文件打包归档为jar1.jar,放置在lib文件夹下

          jar cvf jar1.jar -C classes3/ .
        
        
      • 重用Person类,编写第二个java程序jarDemo2.java,放置在src文件夹下

          package cn.xkzhai;
          import com.xkzhai.jar1.Person;
          class Student extends Person{
              private String ID;
          }
        
          class jarDemo2{
              public static void main(String[] args){
                  Student s1 = new Student();
                  s1.setAge(20);
                  System.out.println(s1.getAge());
              }
          }
        
        
      • 编译jarDemo2.java,生成的类文件放置在classes中

          javac -cp lib/jar1.jar -d classes src/jarDemo2.java
        
        
      • 执行

          java -cp lib/jar1.jar;classes cn.xkzhai.jarDemo2
        
        
    6. 设计程序,考查修饰符。public -> protected -> default -> private(选做题)

    7. 编写ArrayTool,把冒泡排序,选择排序,二分法查找等打成jar包。

      • 编写java源文件ArrayTool3.java

          package com.xkzhai.array;
        
          class ArrayTool3{
              int[] arrayData;
        
              public ArrayTool3(){
              }
        
              public ArrayTool3(int[] arrayData){
                  this.arrayData = arrayData;
              }
        
              //1. 打印数组元素
              public void outArray(){
                  for(int i: arrayData){
                      System.out.println(i);
                  }
              }
        
              //2. 冒泡排序
              // 5 4 3 2 1
              // 4 3 2 1 5
              // 3 2 1 4 5
              // 2 1 3 4 5
              // 1 2 3 4 5
              public void bubbleSort(){
                  for(int i = arrayData.length-1;i>0;i--){
                      for(int j=0;j<i;j++){
                          if(arrayData[j]>=arrayData[j+1]){
                              int tmp = arrayData[j];
                              arrayData[j] = arrayData[j+1];
                              arrayData[j+1] = tmp;
                          }
                      }
                  }
              }
        
              //3. 选择排序
              //5 4 3 2 1
              //1 5 4 3 2
              //1 2 5 4 3
              //1 2 3 5 4
              //1 2 3 4 5
              public void selectSort(){
                  for(int i=0;i<arrayData.length-1;i++){
                      for(int j=i;j<=arrayData.length-1;j++){
                          if(arrayData[j]<=arrayData[i]){
                              int tmp = arrayData[j];
                              arrayData[j] = arrayData[i];
                              arrayData[i] = tmp;
                          }
                      }
                  }
              }
        
              //4. 选择排序
              public int halfFind(int c){
                  int min = 0;
                  int max = arrayData.length-1;
                  int index = 0;
        
                  while(min<=max){
                      index = (min+max)/2;
                      if(arrayData[index]>c){
                          max = index-1;
                      }
                      else if(arrayData[index]<c){
                          min = index+1;
                      }
                      else{
                          return index;
                      }
                  }
                  return -1;
              }
          }
        
          class ArrayDemo{
              public static void main(String[] args){
                  ArrayTool3 arr = new ArrayTool3(new int[]{1,3,2,20,12});
                  arr.outArray();
                  arr.bubbleSort();
                  arr.outArray();
        
                  ArrayTool3 arr2 = new ArrayTool3(new int[]{1,3,2,20,12,23,21,19});
                  arr2.outArray();
                  arr2.selectSort();
                  arr2.outArray();
                  System.out.println(arr2.halfFind(-1));
                  System.out.println(arr2.halfFind(12));
              }
          }
        
        
      • 编译,打包

          javac -d classes4 ArrayTool3.java
          //java -cp classes4 com.xkzhai.array.ArrayDemo
          jar cvf ArrayTool.jar -C classes4/ .
        
        
    8. 预习多线程。

    进程

    1. 运行时(runtime)的应用程序

    2. 进程之间的内存不是共享(独占)

    3. 进程间通信使用的socket(套接字)
      进程之间内存是隔离的。内存不共享。

    多线程

    1. 程序(进程)执行过程中,并发执行的代码段

    2. 线程之间共享内存

    3. 创建灵活响应的桌面程序

    4. 每个运行着的线程对应一个stack(方法栈)

    5. 应用程序至少有一个线程(主线程)

    java.lang.Thread

    1. Thread.yield()方法:让当前线程让出CPU抢占权,具有谦逊之意,瞬时的动作

    2. Thread.sleep(int mils)方法:让当前线程休眠指定毫秒数,放弃cpu抢占权,和锁旗标(监控权)没有关系

    3. Thread.join():当前线程等待指定的线程结束后才能继续运行

    4. daemon:守护线程,服务员 Thread.setDaemon(true),为其他线程提供服务的线程。若进程中剩余的线程都是守护线程的话,则进程终止了。

    5. (--) 原子性操作

    6. 线程间通信,共享资源的问题。锁, 将并行转串行,防止并发访问。参照物,锁旗标

       //同步代码块
       synchronized(object lock){
       ...
       }
      

      同步代码块执行期间,线程始终持有对象的监控权,其他线程处于阻塞状态,只能等待

    7. 同步代码块是以当前所在对象做锁旗标
      synchronized(this) === 同步方法

    8. 同步静态方法,使用类作为同步标记
      public static synchronized xxxx(...){
      }

    9. wait()
      让当前线程进入到锁旗标的等待队列,释放cpu抢占权,还释放锁旗标的监控权。
      wait(1000); 设定等待时间,可以避免死锁

    10. notify()
      唤醒在等待队列中的线程,一次只通知一个线程

    11. notifyAll()
      通知所有线程可以抢占cpu和锁旗标监控权,解决死锁问题

      class ThreadDemo10{
      	public static void main(String[] args){
      
      		Pool pool = new Pool();
      
      		Productor p1 = new Productor("生产者1",pool);
      		p1.setName("p1");
      		//Productor p2 = new Productor("生产者2",pool);
      		Consumer c1 = new Consumer("消费者1",pool);
      		c1.setName("c1");
      		Consumer c2 = new Consumer("消费者2",pool);
      		c2.setName("c2");
      
      		p1.start();
      		//p2.start();
      		c1.start();
      		c2.start();
      	}
      }
      
      //生产者
      class Productor extends Thread{
      	private String name;
      	private  Pool pool;
      	static int i = 0;
      
      	public Productor(String name, Pool pool){
      		this.name = name;
      		this.pool = pool;
      	}
      
      	public void run(){
      		//int i=0;
      		while(true){
      			pool.add(i++);
      		}
      	}
      }
      
      //消费者
      class Consumer extends Thread{
      	private String name;
      	private Pool pool;
      	public Consumer(String name, Pool pool){
      		this.name = name;
      		this.pool = pool;
      	}
      
      	public void run(){
      		while(true){
      			pool.remove();
      		}
      	}
      }
      
      //票池
      class Pool{
      	private java.util.List<Integer> list = new java.util.ArrayList<Integer>();
      	//容器最大值
      	private int MAX = 1;
      
      	//添加元素
      	public void add(int n){
      
      		synchronized(this){
      			try{
      				String name = Thread.currentThread().getName();
      				while(list.size() == MAX){
      					System.out.println(name+".wait()");
      					this.wait();
      				}
      				list.add(n);
      				System.out.println(name+"+: "+n);
      				System.out.println(name+".notify()");
      				this.notifyAll();
      			}
      			catch(Exception e){
      				e.printStackTrace();
      			}
      		}
      	}
      
      	//删除元素
      	public int remove(){
      
      		synchronized(this){
      			try{
      				String name = Thread.currentThread().getName();
      				while(list.size() == 0){
      					System.out.println(name+".wait()");
      					this.wait();
      				}
      				int i = list.remove(0);
      				System.out.println(name+"-:"+i);
      				System.out.println(name+".notify()");
      				this.notifyAll();
      				return i;
      			}
      			catch(Exception e){
      				e.printStackTrace();
      			}
      			return -1;
      		}
      	}
      }
      

    作业

    1. 一共100个馒头,40个工人,每个工人最多能吃3个馒头,使用多线程输出所有工人吃馒头的情况

    2. 5辆汽车过隧道,隧道一次只能通过一辆汽车。每辆汽车通过时间不固定,
      机动车通过时间3秒,三轮车通过时间5秒,畜力车通过时间10秒,5辆车分别是2辆机动车,2辆畜力车,1辆三轮车,通过多线程模拟通过隧道的情况。提示:Car ThreeCar CowCar

    3. 用多线程模拟蜜蜂和熊的关系
      蜜蜂是生产者,熊是消费者,蜜蜂生产蜂蜜是累加的过程,熊吃蜂蜜是批量(满20吃掉)的过程,生产者和消费者之间使用通知方式告知对方,注意不能出现死锁现象。
      100只蜜蜂,每次生产的蜂蜜是1
      熊吃蜂蜜是20(批量的情况)

  • 相关阅读:
    实验 6:OpenDaylight 实验——OpenDaylight 及 Postman 实现流表下发
    实验 5:OpenFlow 协议分析和 OpenDaylight 安装
    实验 4:Open vSwitch 实验——Mininet 中使用 OVS 命令
    实验 3:Mininet 实验——测量路径的损耗率
    软件工程第一次作业
    实验 2:Mininet 实验——拓扑的命令脚本生成
    实验 1:Mininet 源码安装和可视化拓扑工具
    软件工程第一次作业
    软工实践个人总结
    2020软工第二次结对作业
  • 原文地址:https://www.cnblogs.com/SweetZxl/p/9742485.html
Copyright © 2020-2023  润新知