多线程与UDP编程

多线程

 需求:某电影院出售某些电影的票(复联3,红高粱....),有三个窗口同时进行售票(100张票),请您设计一个程序,模拟电影院售票

  两种方式:
  继承

  接口

继承:

package westos._2;

public class SellTicket extends Thread {
	// 为让外界不更改票数,用private修饰,让每个线程都使用同一个数据,用static修饰
	private static int ticket = 100;

	public void run() {
		while (true) {
			if (ticket > 0)
				System.out.println(getName() + "正在出售第" + (ticket--) + "张票");
		}
	}

}
package westos._2;

public class SellTicketDemo {
	public static void main(String[] args) {
		// 创建线程
		SellTicket s1 = new SellTicket();
		SellTicket s2 = new SellTicket();
		SellTicket s3 = new SellTicket();
		// 定义名称
		s1.setName("窗口1");
		s2.setName("窗口2");
		s3.setName("窗口3");

		s1.start();
		s2.start();
		s3.start();

	}
}

接口:

package westos._1;

public class SellTicket implements Runnable {
	private int ticket = 100;

	@Override
	public void run() {
		// TODO Auto-generated method stub
		while (true) {

			if (ticket > 0) {
				System.out.println(Thread.currentThread().getName() + "正在卖第" + (ticket--) + "张票");
			}
		}
	}

}
package westos._1;

public class SellTicketDemo {
	public static void main(String[] args) {
		SellTicket st = new SellTicket();
		
		Thread t1 = new Thread(st, "窗口1");
		Thread t2 = new Thread(st, "窗口2");
		Thread t3 = new Thread(st, "窗口3");
		
		t1.start();
		t2.start();
		t3.start();

	}
}

售票加入延迟特点:

程序的设计是好的,但是结果有一些问题

  1)同一张票被卖了多次
   CPU的执行有一个特点(具有原子性操作:最简单最基本的操作)
   2)出现了0或者负票
   (延迟操作+线程的执行随机性)
  

package westos._3;

public class SellTicket implements Runnable {
	private int ticket = 100;

	@Override
	public void run() {
		// TODO Auto-generated method stub
		while (true) {

			if (ticket > 0) {
				// 延时100毫秒
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				// 100张票
				// 为什么会出现同一张票被卖多次?
				/*
				 * 出现同票的原因:CPU的执行有一个特点(具有原子性操作:最简单最基本的操作) t1线程进来,睡完了,100张票 原子性操作:记录以前的值
				 * 接着tickets-- :票变成99张票 在马上输出99张票之前,t2/t3进来,直接输出记录的以前那个tickets的值 出现:
				 * 窗口1正在出售第100张票 窗口3正在出售第99张票 窗口2正在出售第99张票
				 * 
				 * 原子性操作
				 * 
				 */
				System.out.println(Thread.currentThread().getName() + "正在出售第" + (ticket--) + "张票");
				/**
				 * 理想状态: t1正在出售第3张票 t3正在出售第2张票 t2正在出售第1张票 ... 负票 t1出售第0张票 (延迟操作+线程的执行随机性)
				 * t3正在出售-1张票
				 * 
				 */
			}
		}
	}

}

package westos._3;

import westos._1.SellTicket;

public class SellTicketDemo {
	public static void main(String[] args) {
		// 创建资源对象
		SellTicket st = new SellTicket();
		// 创建线程并添加资源
		Thread t1 = new Thread(st, "窗口1");
		Thread t2 = new Thread(st, "窗口2");
		Thread t3 = new Thread(st, "窗口3");
		// 启动线程
		t1.start();
		t2.start();
		t3.start();

	}
}

如何解决多线程的安全问题?

   校验一个多线程程序是否有安全问题的隐患的前提条件:

                     1.当前程序是否是多线程环境

                     2.是否有共享数据

                     3.是否有多条语句对共享数据进行操作

              看当前案例是否有多线程的安全问题:

  1)是否是多线程环境
   2)是否有共享数据
   3)是否有多条语句对共享数据进行操作  是
  
              现在就需要解决安全问题:
   1)多线程环境 不能解决
   2)对共享数据进行优化 不能解决
   3)解决将多条语句对共享数据这一环进行解决
  
   解决方案:就是将多条语句对共享数据操作的代码,用一个代码包起来---->代码--->同步代码块
  
   格式:
   synchronized(锁对象){
   针对多条语句对共享数据操作代码;
   }
  
   锁对象:肯定一个对象,随便创建一个对象(匿名对象) 
   给刚才的这个程序加入了同步代码块,但是锁对象使用的匿名对象(每一个线程进来都有自己的锁),还是没有解决!
  
   锁对象:每一个线程最终使用的锁对象,只能是同一把锁
package westos._4;

public class SellTicket implements Runnable {
	// 定义100张票
	private int ticket = 100;
	// 定义对象,保证每个线程进来都有自己的锁
	private Object obj = new Object();

	@Override
	public void run() {
		// TODO Auto-generated method stub
		while (true) {
			// 使用同步锁
			synchronized (obj) {
				if (ticket > 0) {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + "正在出售第" + (ticket--) + "张票");
				}
			}
		}
	}
}
package westos._4;

public class SellTicketDemo {
	public static void main(String[] args) {
		// 定义资源对象
		SellTicket st = new SellTicket();
		// 定义线程对象
		Thread t1 = new Thread(st, "窗口1");
		Thread t2 = new Thread(st, "窗口2");
		Thread t3 = new Thread(st, "窗口3");
		// 启动线程
		t1.start();
		t2.start();
		t3.start();
	}
}

静态同步方法public  synchronized static void show(){}:该方法内代码块同步执行 

非静态同步方法public  synchronized void show(){}:该方法内代码块同步执行
package westos._5;

public class SellTicket implements Runnable {
	// 定义100张票
	private static int ticket = 100;
	// 定义对象,保证每个线程进来都有自己的锁
	// private Object obj = new Object();

	/*
	 * @Override public void run() { // TODO Auto-generated method stub while (true)
	 * { // 使用同步锁 synchronized (this) {//非静态可以直接定义参数为this if (ticket > 0) { try {
	 * Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated
	 * catch block e.printStackTrace(); }
	 * System.out.println(Thread.currentThread().getName() + "正在出售第" + (ticket--) +
	 * "张票"); } } } }
	 */
	private int i = 0;

	@Override
	public void run() {
		// TODO Auto-generated method stub
		while (true) {
			if (i % 2 == 0) {
				// 使用静态同步锁
				synchronized (SellTicket.class) {// 将同步锁定义为静态方法,参数为类名.class
					if (ticket > 0) {
						try {
							Thread.sleep(100);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						System.out.println(Thread.currentThread().getName() + "正在出售第" + (ticket--) + "张票");
					}
				}
			} else {
				show();
			}
			i++;
		}
	}

	// 静态同步方法,代码同步执行
	public synchronized static void show() {
		if (ticket > 0) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "正在出售第" + (ticket--) + "张票");
		}
	}
}

package westos._5;

import westos._4.SellTicket;

public class SellTicketDemo {
	public static void main(String[] args) {
		// 定义资源对象
		SellTicket st = new SellTicket();
		// 定义线程对象
		Thread t1 = new Thread(st, "窗口1");
		Thread t2 = new Thread(st, "窗口2");
		Thread t3 = new Thread(st, "窗口3");
		// 启动线程
		t1.start();
		t2.start();
		t3.start();
	}

}
线程安全的类
StringBuffer sb = new StringBuffer() ;
Vector<String> v = new Vector<String>() ;

Hashtable<String, String> hm = new Hashtable<String,String>() ;

   Vector<String>它线程安全的类,还是不习惯使用这个集合,通过ArrayList集合:线程不安全的类

   Collections中有:

           public static<T> List<T> synchronizedList(List<T> list) 返回指定列表支持的同步列表(线程安全的)              

               例: List <T> list=new ArrayList()//线程不安全的类

            List<T> list2=Collections.synchronizedList(list)//线程安全的类

Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。此实现允许更灵活的结构
  可以使用Lock锁进行具体的锁定操作类 提供了具体的实现类:ReentrantLock
  加锁并且去释放锁

 

package westos._6;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SellTicket implements Runnable {
	private int ticket = 100;
	// 创建Lock接口对象
	private Lock lock = new ReentrantLock();

	@Override
	public void run() {
		// TODO Auto-generated method stub
		while (true) {
			// 获取锁
			try {
				lock.lock();
				if (ticket > 0) {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + "正在出售第" + (ticket--) + "张票");
				}
			} finally {
				// 关闭锁
				if (lock != null)
					lock.unlock();
			}
		}
	}
}
package westos._6;

import westos._4.SellTicket;

public class SellTicketDemo {
public static void main(String[] args) {
	// 定义资源对象
	SellTicket st = new SellTicket();
	// 定义线程对象
	Thread t1 = new Thread(st, "窗口1");
	Thread t2 = new Thread(st, "窗口2");
	Thread t3 = new Thread(st, "窗口3");
	// 启动线程
	t1.start();
	t2.start();
	t3.start();
}
}
解决了多线程安全问题,但是还是有些问题:
1)执行效率低
2)会产生死锁
两个或两个以上的线程,在执行的过程中出现互相等待的情况,就叫做死锁!
package westos._7;

public class MyLock {
	// 定义两个对象
	public final static Object obja = new Object();
	public final static Object objb = new Object();
}
package westos._7;

public class SellTicket extends Thread {
	// 通过有参构造获取flag
	private boolean flag;

	public SellTicket(boolean flag) {
		this.flag = flag;
	}

	public void run() {
		if (flag) {
			synchronized (MyLock.obja) {
				System.out.println("if obja");
				synchronized (MyLock.objb) {
					System.out.println("if objb");
				}
			}
		} else {
			synchronized (MyLock.objb) {
				System.out.println("else objb");
				synchronized (MyLock.obja) {
					System.out.println("else obja");
				}
			}
		}
	}
	/**
	 * 第一种情况: if ObjA else objB
	 * 
	 * 第二种情况 else objB if ObjA
	 * 
	 * 第三种情况: 理想状态 else objB else objA if ObjA if objB
	 * 
	 * if ObjA if objB else objB else objA
	 * 
	 * 
	 */
}
package westos._7;

public class SellTicketDemo {
	public static void main(String[] args) {
		SellTicket st = new SellTicket(true);
		SellTicket st1 = new SellTicket(false);
		st.start();
		st1.start();
	}
}
分析:
  Student类: 资源类
   SetThread:设置学生的数据(生产者线程)
   GetThread:获取(输出)学生数据(消费者线程)
   StudentDemo:测试类
  

  需求:SetThread线程给学生对象进行赋值,在通过消费者线程输出该学生数据,设计这样一个程序!

null----0 按照刚才的思路,发现有一个问题,的数据null---0
  
  解决方案:线程死锁的注意事项:要保证生产者线程和消费者线程针对同一个对象进行操作的!
   在外部创建一个学生对象,将这个学生对象通过构造方法传入到各个线程中

  
package westos._7;

//Student类
public class Student {
	int age;
	String name;
}
package westos._7;

//给成员变量赋值
public class SetStudent extends Thread {
	private Student s;

	public SetStudent(Student s) {
		this.s = s;
	}

	public void run() {
		s.name = "王菲";
		s.age = 23;

	}
}
package westos._7;

//打印成员变量的值
public class GetStudent extends Thread {
	private Student s;

	public GetStudent(Student s) {
		this.s = s;
	}

	public void run() {
		System.out.println(s.age + "--" + s.name);
	}
}
package westos._7;

public class StudentDemo {
	public static void main(String[] args) {
		// 创建Student对象
		Student s = new Student();
		// 创建线程
		SetStudent st = new SetStudent(s);
		GetStudent gt = new GetStudent(s);
		
		gt.start();
		st.start();
	}
}

分析:
  Student类: 资源类
   SetThread:设置学生的数据(生产者线程)
   GetThread:获取(输出)学生数据(消费者线程)
   StudentDemo:测试类
  
  需求:SetThread线程给学生对象进行赋值,在通过消费者线程输出该学生数据,设计这样一个程序!
    null----0 按照刚才的思路,发现有一个问题,的数据null---0
  解决方案:线程死锁的注意事项:要保证生产者线程和消费者线程针对同一个对象进行操作的!
   在外部创建一个学生对象,将这个学生对象通过构造方法传入到各个线程中
   需求:消费者线程,和生产者线程加入循环操作,改进
  
   又有问题:
   1)同一个人的姓名和年龄出现多次
   2)姓名和年龄不符
  为什么?
   1)CPU的一点点时间片,在某一个时间点,足够它执行很多次
   2)线程具有随机性
 
 解决方案:
  1)是否是多线程环境
  2)是否有功共享数据
  3)是否有多条语句对共享数据进行操作
 
  同步机制(同步代码块/同步方法)
  开发中,使用synchronized(Lock锁也可以)同步代码块将多条语句对共享数据的操作包起来!
 
package westos._7;

//Student类
public class Student {
	int age;
	String name;
}
package westos._7;

//给成员变量赋值
public class SetStudent extends Thread {
	private Student s;

	public SetStudent(Student s) {
		this.s = s;
	}

	private int i = 0;

	public void run() {
		while (true) {
			// 使用同步锁
			synchronized (s) {
				if (i % 2 == 0) {
					s.name = "王菲";
					s.age = 23;
				} else {
					s.age = 34;
					s.name = "莫文蔚";
				}
				i++;
			}
		}
	}
}
package westos._7;

//打印成员变量的值
public class GetStudent extends Thread {
	private Student s;

	public GetStudent(Student s) {
		this.s = s;
	}

	public void run() {
		while (true) {
			synchronized (s) {
				System.out.println(s.age + "--" + s.name);
			}
		}
	}
}
package westos._7;

public class StudentDemo {
	public static void main(String[] args) {
		// 创建Student对象
		Student s = new Student();
		// 创建线程
		SetStudent st = new SetStudent(s);
		GetStudent gt = new GetStudent(s);
		
		gt.start();
		st.start();
	}
}
继续改进:
  上面的代码改进之后,虽然加入了同步机制,但是打印一打印一大片同样,让数据依次打印数据!
 
  如何解决:
  就使用的是Java的等待唤醒机制
 
 面试题:
  wait(),notify(),notifyAll() 这些方法为什么会定义在Object类中呢?
 
 这些方法好像就属于线程的方法,但是Thread类中并没有这些方法,多线程中同步锁对象:任意的Java类
  这些方法都和锁对象有关系,所以定义在Object类
 
package westos._7;

//Student类
public class Student {
	int age;
	String name;
	boolean flag;
}
package westos._7;

//给成员变量赋值
public class SetStudent extends Thread {
	private Student s;

	public SetStudent(Student s) {
		this.s = s;
	}

	private int i = 0;

	public void run() {
		while (true) {
			// 使用同步锁
			synchronized (s) {
				// 如果更改数据了
				if (s.flag) {
					try {
						s.wait();// 等待gt读数据
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				if (i % 2 == 0) {
					s.name = "王菲";
					s.age = 23;
				} else {
					s.age = 34;
					s.name = "莫文蔚";
				}
				i++;
				// 更改数据了,更改flag为true
				s.flag = true;
				// 唤醒gt
				s.notify();
			}
		}
	}
}
package westos._7;

//打印成员变量的值
public class GetStudent extends Thread {
	private Student s;

	public GetStudent(Student s) {
		this.s = s;
	}

	public void run() {
		while (true) {
			synchronized (s) {
				// 如果没有更改数据
				if (!s.flag) {
					try {
						s.wait();// 等待st更改数据
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				System.out.println(s.age + "--" + s.name);
				// 读过更改的数据了,更改flag为false
				s.flag = false;
				// 唤醒st重新更改数据
				s.notify();
			}
		}
	}
}
package westos._7;

public class StudentDemo {
	public static void main(String[] args) {
		// 创建Student对象
		Student s = new Student();
		// 创建线程
		SetStudent st = new SetStudent(s);
		GetStudent gt = new GetStudent(s);

		gt.start();
		st.start();
	}
}
线程组:

线程组表示一个线程的集合。此外,线程组也可以包含其他线程组 

    public final ThreadGroup getThreadGroup():返回该线程的线程组

    public final String getName:获取该线程组的名称

   所有线程默认的线程组为main

   public ThreadGroup(String name):构造一个线程组,并定义名  

Thread(ThreadGroup group, Runnable target, String name) 创建一个线程,并把该线程定义在指定的线程组中

package westos._8;

public class MyRunnable implements Runnable {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		for(int i=0;i<100;i++) {
			System.out.println(Thread.currentThread().getName()+":"+i);
		}
		
	}

}
package westos._8;

public class MyThreadDemo {
	public static void main(String[] args) {
		method1();
		method2();
	}

	private static void method2() {
		// TODO Auto-generated method stub
		// 创建一个线程组并定义名称
		ThreadGroup tg = new ThreadGroup("这是一个线程组");
		// 定义资源对象
		MyRunnable mr = new MyRunnable();
		// 创建线程,并把该线程定义在该线程组中
		Thread t1 = new Thread(tg, mr, "线程1");
		Thread t2 = new Thread(tg, mr, "线程2");
		System.out.println(tg.getName());

	}

	private static void method1() {
		// 定义资源对象
		MyRunnable mr = new MyRunnable();
		// 创建线程
		Thread t1 = new Thread(mr, "线程1");
		Thread t2 = new Thread(mr, "线程2");
		// 返回线程的线程组
		ThreadGroup tg1 = t1.getThreadGroup();
		ThreadGroup tg2 = t2.getThreadGroup();
		// 获取先线程组的名称
		System.out.println(tg1.getName());
		System.out.println(tg2.getName());
		System.out.println(Thread.currentThread().getThreadGroup().getName());// 所有线程组默认的名称为main
	}
}

线程池:

  线程池(某个线程执行完毕,反复利用线程对象)
线程池:多个线程执行完毕,它会重新回到线程池中,等待被利用,不会变成垃圾!
  和线程池有关的类
 类 Executors: 一种工厂类
  方法:
  和线程池的创建有关系
  public static ExecutorService newFixedThreadPool(int nThreads)
  创建一个可重用固定线程数的线程池
 ExecutorService:可以执行异步任务

  创建一个线程池,执行接口中的方法

 Future:接口,Future 表示异步计算的结果
 线程池调用完毕可以关闭的
  void shutdown():关闭之前,会提交刚才的任务

 提交:Future<?> submit(Runnable task)

package westos._9;

public class MyRunnable implements Runnable {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		for (int i = 0; i < 100; i++)
			System.out.println(Thread.currentThread().getName() + ":" + i);
	}

}
package westos._9;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class ExecutorsDemo {
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		// 创建线程池,并定义该线程池内的线程数
		ExecutorService es = Executors.newFixedThreadPool(3);
		ExecutorService es2 = Executors.newFixedThreadPool(3);
		// 提交Runnable接口的方法
		es.submit(new MyRunnable());
		es.submit(new MyRunnable());
		Future<?> f = es.submit(new MyRunnable());
         
		es2.submit(new MyRunnable());
		es2.submit(new MyRunnable());
		Future<?> f2 = es2.submit(new MyRunnable());
		System.out.println(f);
		System.out.println(f2);
		// 关闭线程池
		es.shutdown();
		es2.shutdown();
	}

}
<T> Future<T> submit(Callable<T> task)提交一个返回值的任务用于执行,返回一个表示任务的未决结果的 Future
 
package westos_10;

import java.util.concurrent.Callable;

public class MyCallable implements Callable<Integer>{
	//定义成员变量
	private int a;
	public MyCallable(int a) {
		this.a=a;
	}

	@Override
	public Integer call() throws Exception {
		// TODO Auto-generated method stub
		int sum=0;
		for(int i=1;i<=a;i++) {
		sum+=i;	
		System.out.println(Thread.currentThread().getName()+":"+i);
	}
		return sum;
}
}
package westos_10;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class ExecutorsDemo {
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		// 创建线程池,并定义线程数
		ExecutorService es = Executors.newFixedThreadPool(3);
		// 提交任务
		Future<Integer> f1 = es.submit(new MyCallable(101));
		Future<Integer> f2 = es.submit(new MyCallable(102));
		Future<Integer> f3 = es.submit(new MyCallable(103));
		Future<Integer> f4 = es.submit(new MyCallable(104));//线程池已经满了,该线程不会在控制台输出,但会返回结果
		// 获取结果
		System.out.println(f1.get());
		System.out.println(f2.get());
		System.out.println(f3.get());
		System.out.println(f4.get());
		//关闭线程池
		es.shutdown();
	}
}

简单工厂模式--->静态工厂模式

   设计一个工厂类:

        工厂类提供了一些静态方法,间接地创建具体对象

优点 :不需要在创建具体类的对象,而是把创建的工作交给了工厂类来创建!

弊端:如果有新的对象增加,或者某些对象的创建方式不同,就需要不断的修改工厂类,不利于后期的维护
package westos._11;

//动物接口
public interface Animal {
	public abstract void eat();
}
package westos._11;

//狗
public class Dog implements Animal {
	public void eat() {
		System.out.println("狗吃肉不吐骨头");
	}

}
package westos._11;

//猪
public class Pig implements Animal {
	public void eat() {
		System.out.println("猪啥都吃");
	}
}
package westos._11;

public class AnimalFactory {
	// 无参构造私有化
	private AnimalFactory() {
	}

	// 第一种方法,分别调用每个动物的返回对象方法
	/*
	 * public static Pig createPig() { return new Pig(); } public static Dog
	 * createDog() { return new Dog(); }
	 */
	// 以多态形式,根据参数的不同返回不同的动物对象
	public static Animal createAnimal(String animal) {
		if ("pig".equals(animal)) {
			return new Pig();
		}
		if ("dog".equals(animal)) {
			return new Dog();
		}
		return null;

	}
}
package westos._11;

public class AnimalDemo {
	public static void main(String[] args) {
		// 第一种方法
		/*
		 * Dog dog=AnimalFactory.createDog(); dog.eat(); Pig
		 * pig=AnimalFactory.createPig(); pig.eat();
		 */
		// Animal al=AnimalFactory.createAnimal("cat");//NullPointerException空指针异常
		// al.eat();
		// 第二种方法,多态
		Animal al = AnimalFactory.createAnimal("cat");
		Animal al1 = AnimalFactory.createAnimal("dog");
		Animal al2 = AnimalFactory.createAnimal("pig");
		al1.eat();
		al2.eat();

		if (al != null) {
			al.eat();
		} else {
			System.out.println("该动物园没有此类动物");
		}
	}

}
工厂方法模式
  提供一个抽象类(抽象工厂)还需要提供一个接口(工厂接口),每一个具体的类都有对应的工厂类(实现工厂接口)
  具体对象的创建工作由继承抽象工厂的具体类实现
 
 优点:
  客户端不需要在负责对象的创建(不需显示创建具体对象),从而明确了各个类的职责,
  如果有新的对象增加,只需要增加一个具体的类和具体的工厂类即可,不影响已有的代码,后期维护容易,增强了系统的扩展性
弊端:
书写代码量大了!

package westos._12;
//动物类
public interface Animal {
public void eat();
}
package westos._12;
//动物工厂
public interface Factory {
Animal createAnimal();
}
package westos._12;
//猫
public class Cat implements Animal {

	@Override
	public void eat() {
		// TODO Auto-generated method stub
    System.out.println("猫现在都不会抓老鼠了");
	}

}
package westos._12;
//猫工厂
public class CatFactory implements Factory {

	public Animal createAnimal() {
		// TODO Auto-generated method stub
		return new Cat();
	}

}
package westos._12;
//狗
public class Dog implements Animal {
    @Override
	public void eat() {
		// TODO Auto-generated method stub
     System.out.println("狼行千里吃肉,狗行千里吃xxx");
	}

}
package westos._12;
//狗工厂
public class DogFactory implements Factory {

	@Override
	public Animal createAnimal() {
		// TODO Auto-generated method stub
		return new Dog();
	}

}
package westos._12;

public class AnimalDemo {
public static void main(String[] args) {
	//动物工厂以多态形式创建各自的动物工厂,返回不同的动物对象
	Factory f=new CatFactory();
	//动物以多态形式创建动物对象
	Animal al=f.createAnimal();
	al.eat();
	f=new DogFactory();
	al=f.createAnimal();
	al.eat();
}
}




设计模式之单例模式
  单例模式核心思想:某些类的对象在创建的时候 ,在系统内存始终只有一个对象!
  单例模式分类:
  1)饿汉式 2)懒汉式(类似于多线程环境..)
  饿汉式:
  在加载那个类的时候,对象的创建工作就已经完成了!
 两种分类在设计上几乎一样:
1)定义个类,将该类的无参构造方法私有化
2)在该类的成员位置创建该类对象 并且一定要私有化,防止外界更改这个对象

  3)在该类中提供静态成员方法(返回值就是创建的那个对象),能被当前类直接调用,static修饰

package westos._13;

public class Student {
	// 饿汉式,对象在类加载的时候已经在成员变量位置创建好了
	// 无参构造私有化,防止创建多个对象
	private Student() {
	}

	// 创建本类对象,并静态私有化
	private static Student s = new Student();

	// 提供静态方法
	public static Student getStudent() {
		return s;
	}
}
package westos._13;

public class StudentDemo {
	public static void main(String[] args) {
		// 创建对象
		Student s1 = Student.getStudent();
		Student s2 = Student.getStudent();
		System.out.println(s1 == s2);// true

	}
}

懒汉式:
  符合单例模式核心思想
   1)自定义一个类,将无参构造私有化
   2)在成员位置声明变量
   3)提供公共静态功能,在里面判断的创建该类对象,返回该类对象
   如果是开发中,那么就使用饿汉式(饿汉式它不会出现问题的单例模式)
  如果是面试中,那么使用懒汉式(因为他是可能出现问题的一种单例模式)
   面试题:
  你使用过单例模式吗?简单介绍一种单例模式,请用代码设计
   面试官想问的是:使用设计单例的懒汉式,能否想到使用同步机制解决线程的安全问题..
   懒汉式(延迟加载 -->懒加载)
  可能会出现问题
   ---> 多线程的问题
   --->校验多线程安全问题的标准
   1)是否是多线程环境
   2)是否有共享数据
   3)是否有多条语句对共享数据进行操作  (使用同步机制进行操作)
package westos._13;

public class Student {
	// 无参构造私有化,防止创建多个对象
	private Student() {
	}
	// 饱汉式,延迟加载,需要使用同步加载模式避免会出现的单例问题
	private static Student s = null;
        //静态的同步方法
	public synchronized static Student getStudent() {
		if (s == null) {//第一次调用时会创建本类对象,保证以后调用的都是同一个对象
			s = new Student();
		}
		return s;
	}
}
package westos._13;

public class StudentDemo {
	public static void main(String[] args) {
		// 创建对象
		Student s1 = Student.getStudent();
		Student s2 = Student.getStudent();
		System.out.println(s1 == s2);// true

	}
}
Runtime
  每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。
  public static Runtime getRuntime()返回与当前 Java 应用程序相关的运行时对象
public Process exec(String command)
             throws IOException在单独的进程中执行指定的字符串命令。
package westos._13;

import java.io.IOException;

public class RuntimeDemo {
	public static void main(String[] args) throws IOException {
		// 单例模式
		Runtime rt = Runtime.getRuntime();
		// 打开相关的运行软件
		rt.exec("calc");
		rt.exec("notepad");
	}
}

网络编程:

UDP编程:

计算机网络:

多台计算机通过网络协议,实现网络资源共享和信息传递!

http://localhost:端口号 (80)www.baidu.com


username:admin
password:%AE%.... MD5算法   加密很难解密


网络通信三要素


1)ip地址
2)端口号
3)应该有一些规则(协议UDP/TCP)

举例:
我想和高圆圆聊天...
1)找到她,才能和她说话------>IP地址
2)假设找她了,怎么说呢?
对着她耳朵说话------->port端口号
3)要对她:i love you 
假设不懂英文,----->定义规则(协议)

IP地址:
192.168.10.1 (通过8421码将可以由0,1组成的一些数据)
点分十进制法:十进制.十进制.十进制.十进制  书写简单

11000000.0000100....

Ip地址的分类:

IP地址的组成
IP地址 = 网络号码+主机地址


A类IP地址:第一段号码为网络号码,剩下的三段号码为本地计算机的号码
一般情况:国防部/大的国部门
B类IP地址:前二段号码为网络号码,剩下的二段号码为本地计算机的号码
一般情况:大学里面的多媒体教室
C类IP地址:前三段号码为网络号码,剩下的一段号码为本地计算机的号码
私人地址


A类 1.0.0.1---127.255.255.254 (1)10.X.X.X是私有地址(私有地址就是在互联网上不使用,而被用在局域网络中的地址) (2)127.X.X.X是保留地址,用做循环测试用的。
B类 128.0.0.1---191.255.255.254 172.16.0.0---172.31.255.255是私有地址。169.254.X.X是保留地址。
C类 192.0.0.1---223.255.255.254 192.168.X.X是私有地址
D类 224.0.0.1---239.255.255.254
E类 240.0.0.1---247.255.255.254


127.0.0.1--->表示本地计算机的回环地址
dos
ipconfig
ping ip地址 是否能通信

声呐系统(二战)  


端口号:0~65535有效端口号
0-1024属于保留端口

mysql:3306 

协议:
UDP协议 --->UDP编程
不需要建立连接通道的
数据大小有限制
不可靠连接
执行效率高
TCP协议 ---->TCP编程
需要建立连接通道
数据大小无限制
可靠连接
执行效率低


打电话:看成TCP协议  建立连接通道
发短信:UDP协议 不需要建立连接通道
InetAddress:类表示互联网协议 (IP) 地址
 
 如果一个类中没有构造方法,没有字段,只有成员方法?有什么特征
 1)应该有一些静态功能(Math类,Arrays,Collections...)
 2)可能符合一种单例模式(饿汉/懒汉)
 3)该类中的某些静态成员方法的返回值是该类本身
 
  举例
  public class Demo{
 
  public static Demo getDemo(){
  new Demo() ;
  }
  }
 常用方法:
  public static InetAddress getByName(String host)
        throws UnknownHostException在给定主机名的情况下确定主机的 IP 地址。
        参数:
        主机名可以是机器名(如 "java.sun.com"),也可以是其 IP 地址的文本表示形式


package westos.org.UDP;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class InterAdressDemo {

public static void main(String[] args) throws UnknownHostException {
	//创建InetAdress对象获取ip地址
	//知道ip地址的主机名
	InetAddress address=InetAddress.getByName("LAPTOP-BF748GHC");
	//获取ip地址的文本形式
	String adr=address.getHostAddress();
	//获取IP地址的主机名
	String name=address.getHostName();
	System.out.println(adr);
	System.out.println(name);
}
}
Udp编程的接收端 开发步骤:
  1)创建Socket对象
  2)创建一个数据报包(接收容器) 
  3)调用Socket对象中的接收的方法
  4)解析实际传递的数据
  5)将解析的数据(ip,数据)展示在控制台上
  6)关闭资源
 注意:
 接收端不要运行多次,会出现异常:
  java.net.BindException: Address already in use: Cannot bind
package westos.org.UDP;
//接收数据
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class ReceiveDemo {
public static void main(String[] args) throws IOException {
	//创建接收端的Socket对象
	DatagramSocket ds=new DatagramSocket(11111);
	//创建接收的数据包
	byte []bys=new byte[1024];
	DatagramPacket dp=new DatagramPacket(bys,0,bys.length);
	//接收数据包
	ds.receive(dp);
	//返回ip地址
	InetAddress address=dp.getAddress();
	String adr=address.getHostAddress();//获取IP地址的文本形式
	System.out.println(adr);
	//获取数据
	byte []bys2=dp.getData();
	//获取接收数据的实际长度
	int len=dp.getLength();
	System.out.println(len);
	System.out.println(new String(bys2));
	//关闭资源
	ds.close();
			
}
}
package westos.org.UDP;
//发送数据
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class SendDemo {
public static void main(String[] args) throws IOException {
	//创建发送端的Socket对象
	DatagramSocket ds=new DatagramSocket();
	//创建发送的数据包,并定义端口号,ip地址,发送的数据为字节数组
	byte []bys="皇马三连冠".getBytes();
	int len=bys.length;
	InetAddress address=InetAddress.getByName("192.168.1.129");
	
	DatagramPacket dp=new DatagramPacket(bys,0,len,address,11111);
	//发送数据包
	ds.send(dp);
	//关闭资源
	ds.close();
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值