javaSE复习总结3

1、线程

Thread类:

  public final String getName():返回该线程的名称

  public final void setName(String name):改变线程名称,使之与参数 name 相同

  getThreadGroup():返回该线程所属的线程组。

 

线程控制:

  public static void sleep(long millis):线程休眠

  public final void join():线程加入( 等待该线程终止)

  public static void yeild():线程礼让(暂停当前正在执行的线程对象,并执行其他线程。)

  public final void setDaemon(boolean on):后台线程

  public final void stop():  已过时。 该方法具有固有的不安全性。用 Thread.stop 来终止线程将释放它已经锁定的所有监视器

  public void interrupt():   中断线程。

 

多线程的实现方案:

1)继承Thread类

步骤
 A:自定义类MyThread继承Thread类。
 B:MyThread类里面重写run()
 C:创建对象
 D:启动线程

public class MyThread extends Thread {

public void run() {
for (int x = 0; x < 200; x++) {
System.out.println(x);
}
}

}

 

public class MyThreadDemo {
public static void main(String[] args) {

  // run():仅仅是封装被线程执行的代码,直接调用是普通方法
  // start():首先启动了线程,然后再由jvm去调用该线程的run()方法。

  // IllegalThreadStateException:非法的线程状态异常

// 创建两个线程对象
  MyThread my1 = new MyThread();
  MyThread my2 = new MyThread();

// 启动线程

  my1.start();
  my2.start();
}
}

 

2)实现Runnable接口(实现接口可以避免java单继承带来的局限性)

步骤:
 A:自定义类MyRunnable实现Runnable接口
 B:重写run()方法
 C:创建MyRunnable类的对象
 D:创建Thread类的对象,并把C步骤的对象作为构造参数传递

 

public class MyRunnable implements Runnable {

public void run() {
for (int x = 0; x < 100; x++) {
// 由于实现接口的方式就不能直接使用Thread类的方法了,但是可以间接的使用
System.out.println(Thread.currentThread().getName() + ":" + x);
}
}

}

 

public class MyRunnableDemo {
public static void main(String[] args) {
// 创建MyRunnable类的对象
  MyRunnable my = new MyRunnable();

// 创建Thread类的对象,并把C步骤的对象作为构造参数传递

// Thread(Runnable target, String name)
  Thread t1 = new Thread(my, "aa");
  Thread t2 = new Thread(my, "bb");

  t1.start();
  t2.start();
}
}

 

解决线程安全问题:

1)同步代码块:

  synchronized(对象){
  需要同步的代码;
  }


同步可以解决安全问题的根本原因就在那个对象上。该对象如同锁的功能。多个线程必须是同一把锁。

public class SellTicket implements Runnable {
// 定义100张票
  private int tickets = 100;
//创建锁对象
  private Object obj = new Object();


@Override
public void run() {
  while (true) {
  synchronized (obj) {
    if (tickets > 0) {
      try {
        Thread.sleep(100);
      } catch (InterruptedException e) {
        e.printStackTrace();
  }
    System.out.println(Thread.currentThread().getName()+ "正在出售第" + (tickets--) + "张票");
}
}
}
}
}

 

 

2)同步方法:把同步加在方法上

  普通方法(同步对象是this)

private synchronized void sellTicket() {

if (tickets > 0) {
   try {
  Thread.sleep(100);
} catch (InterruptedException e) {
     e.printStackTrace();
   }
  System.out.println(Thread.currentThread().getName()+ "正在出售第" + (tickets--) + "张票 ");
   }
}

 

public void run() {
while (true) {
if(x%2==0){
synchronized (this) {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ "正在出售第" + (tickets--) + "张票 ");
}
}
}else {}

 

静态方法的锁对象是:类的字节码文件对象

private static synchronized void sellTicket() {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ "正在出售第" + (tickets--) + "张票 ");
}
}
}

 

public void run() {
while (true) {
if(x%2==0){
synchronized (SellTicket.class) {//这里不可能是this,因为静态中没有this 静态是随着类的加载而加载,首先进内存的是类的字节码文件
if (tickets > 0) {
try {
Thread.sleep(100);

 

Lock锁

  void lock():获取锁。(如果锁不可用,出于线程调度目的,将禁用当前线程,并且在获得锁之前,该线程将一直处于休眠状态。)

  void unlock():释放锁

 

public class SellTicket implements Runnable {

// 定义票
  private int tickets = 100;

// 定义锁对象
  private Lock lock = new ReentrantLock();

@Override
  public void run() {
  while (true) {
    try {
// 加锁
      lock.lock();
      if (tickets > 0) {
      try {
        Thread.sleep(100);
      } catch (InterruptedException e) {
         e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName()+ "正在出售第" + (tickets--) + "张票");
  }
} finally {
// 释放锁
  lock.unlock();
}
}
}

}

 

 

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

  程序启动一个新线程的成本很高,因为涉及到与操作系统的交互,而使用线程池可以很好的提高性能

 

JDK5新增了Executors工厂类来产生线程池

方法:

  public static ExectorService newCachedThreadPool():开启具有缓存功能的线程池

  public static ExectorService newFixedThreadPool(int nThreads):创建指定数量的线程池

  public static ExectorService  newSingleThreadExector():创建一个

这些方法的返回值是ExectorsService对象,该对象表示一个线程池,可以执行Runnable对象和Callable对象代表的线程

 

public static void main(String[] args) {
// 创建一个线程池对象,控制要创建几个线程对象。
// public static ExecutorService newFixedThreadPool(int nThreads)
  ExecutorService pool = Executors.newFixedThreadPool(2);

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

//Future<?> submit(Runnable task):     提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。
// <T> Future<T> submit(Callable<T> task): 提交一个返回值的任务用于执行,返回一个表示任务的未决结果Future。


  pool.submit(new MyRunnable());
  pool.submit(new MyRunnable());

//结束线程池
  pool.shutdown();//如果不加结束语句,那么线程执行完毕后重新返回池中,以供其他人使用
}

 

public class MyRunnable implements Runnable {

@Override
public void run() {
for (int x = 0; x < 100; x++) {
System.out.println(Thread.currentThread().getName() + ":" + x);
}
}

}

 

 

定时器:

Timer:(extends Object)一种工具,线程用其安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行。

  Timer()
          创建一个新计时器。

  schedule(TimerTask task, long delay)
          安排在指定延迟后执行指定的任务。

  schedule(TimerTask task, long delay, long period)
          安排指定的任务从指定的延迟后开始进行重复的固定延迟执行

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

 

TimerTask(extends Object  implements Runnable

  TimerTask()
          创建一个新的计时器任务

  run()
          此计时器任务要执行的操作。

  cancel()
          取消此计时器任务。

jvm虚拟机的启动是单线程的还是多线程的?
  多线程的。
   原因是垃圾回收线程也要先启动,否则很容易会出现内存溢出。
     现在的垃圾回收线程加上前面的主线程,最低启动了两个线程,所以,jvm的启动其实是多线程的。

 

 

2、设计模式

1)简单工厂模式(静态工厂方法模式):定义一个具体的工厂类负责创建一些类的实例

  缺点:静态工厂负责所有对象的创建,若有新的对象添加或者某些对象的创建方式不同i,就需要不断的修改工厂,不利于后期的维护

 

public abstract class Animal {
  public abstract void eat();
}

//动物工厂

public class AnimalFactory {

//工厂模式的明显特点是 构造方法私有,其他方法是静态的

//构造方法私有只有,外界就不能通过new来创建对象。

  private AnimalFactory() {//下面是静态方法 ,这里构造私有?是因为可以通过类名调用??
  }

//原始版

// public static Dog createDog() {
// return new Dog();
// }

// public static Cat createCat() {
// return new Cat();
// }

 

//下面是改进版

  public static Animal createAnimal(String type) {
    if ("dog".equals(type)) {
      return new Dog();
    } else if ("cat".equals(type)) {
      return new Cat();
    } else {

      return null;
    }
  }
}

public class Cat extends Animal {

@Override
public void eat() {
  System.out.println("猫吃鱼");
}

}

public class Dog extends Animal {

@Override
public void eat() {
  System.out.println("狗吃肉");
}

}

public class AnimalDemo {
public static void main(String[] args) {
// 具体类调用
Dog d = new Dog();
d.eat();
Cat c = new Cat();
c.eat();
System.out.println("------------");

//构造方法私有之后,想要创建对象只能通过工厂类来创造

//返回的对象可以是该类对象或者是该类的子类对象

// 工厂有了后,通过工厂给造
// Dog dd = AnimalFactory.createDog();
// Cat cc = AnimalFactory.createCat();
// dd.eat();
// cc.eat();
// System.out.println("------------");

// 工厂改进后

Animal a = AnimalFactory.createAnimal("dog");
a.eat();
a = AnimalFactory.createAnimal("cat");
a.eat();

// NullPointerException当工厂中没有这种动物的时候将会报空指针异常
a = AnimalFactory.createAnimal("pig");
if (a != null) {//所以这里最好要加上判断是否为null
a.eat();
} else {
System.out.println("对不起,暂时不提供这种动物");
}
}
}

 

2)工厂方法模式:抽象工厂类负责定义创建对象的接口,具体对象的创建工作由继承抽象工厂的具体类实现------客户端不再需要负责对象的创建,从而明确了各个类的职责,如果有新的对象增加,只要增加一个具体的类和具体的工厂类即可,不影响已有代码,利于后期维护

//抽象动物类

public abstract class Animal {
  public abstract void eat();
}

 

//工厂接口

public interface Factory {
  public abstract Animal createAnimal();
}

 

//猫工厂类实现了工厂类

public class CatFactory implements Factory {

@Override
public Animal createAnimal() {
  return new Cat();
}

}

 

//狗工厂类实现了工厂类

public class DogFactory implements Factory {

@Override
public Animal createAnimal() {
  return new Dog();
}

}

//猫类继承动物类

public class Cat extends Animal {

@Override
public void eat() {
  System.out.println("猫吃鱼");
}

}

//狗类实现了动物接口

public class Dog extends Animal {

@Override
public void eat() {
  System.out.println("狗吃肉");
}

}

 

public class AnimalDemo {
public static void main(String[] args) {
// 需求:我要买只狗
  Factory f = new DogFactory();
  Animal a = f.createAnimal();
  a.eat();
  System.out.println("-------");

//需求:我要买只猫
  f = new CatFactory();
  a = f.createAnimal();
  a.eat();
}
}

 

3)单例设计模式:保证类在内存中只有一个对象。

  * 如何保证类在内存中只有一个对象呢?
  * A:把构造方法私有:为的是不让外界造对象
  * B:在成员位置自己创建一个对象
  * C:通过一个公共的方法提供访问

  饿汉式:(不会出问题)

  public class Student {
  // 构造私有为的是不让外界造对象
    private Student() {
    }

  // 静态方法只能访问静态成员变量,加静态
  // 为了不让外界直接访问修改这个值,加private

    private static Student s = new Student();

  // 提供公共的访问方式
  // 为了保证外界能够直接使用该方法,加静态
    public static Student getStudent() {
      return s;
    }
  }

 

public class StudentDemo {
public static void main(String[] args) {
// Student s1 = new Student();
// Student s2 = new Student();
// System.out.println(s1 == s2); // false  因为创建的是不同的对象

// 通过单例得到对象保证类在内存中只有一个对象。

Student s1 = Student.getStudent();
Student s2 = Student.getStudent();
System.out.println(s1 == s2);  //  true内存中只有一个对象

System.out.println(s1); // cn.itcast_03.Student@175078b
System.out.println(s2);// cn.itcast_03.Student@175078b
}
}

  懒汉式:(会出问题)

     A:懒加载(延迟加载)
       B:线程安全问题

public class Teacher {


private Teacher() {
}

private static Teacher t = null;

public synchronized static Teacher getTeacher() {//因为有线程安全问题,所有要加同步
// t1,t2,t3
if (t == null) {
//t1,t2,t3
  t = new Teacher();
}
return t;
}
}

 

public class TeacherDemo {
public static void main(String[] args) {
Teacher t1 = Teacher.getTeacher();
Teacher t2 = Teacher.getTeacher();
System.out.println(t1 == t2);
System.out.println(t1); // cn.itcast_03.Teacher@175078b
System.out.println(t2);// cn.itcast_03.Teacher@175078b
}
}

 

4)模板设计模式:

  就是定义一个算法的骨架,而将具体的算法延迟到子类中来实现

public abstract class GetTime {
// 需求:请给我计算出一段代码的运行时间
  public long getTime() {
    long start = System.currentTimeMillis();

    code();//只有这一块是变化的

    long end = System.currentTimeMillis();

    return end - start;
  }

  public abstract void code();//在定义的时候不知道里面会是什么,相当于是一个模板
}


public class ForDemo extends GetTime {

@Override

//需要什么样的方法,就在重写的code()里面写什么代码

public void code() {
  for (int x = 0; x < 100000; x++) {
  System.out.println(x);
}
}

}

 

public class GetTimeDemo {
public static void main(String[] args) {

  GetTime gt = new ForDemo();
  System.out.println(gt.getTime() + "毫秒"); //在父接口中走code(),但是由于父类中该方法是抽象的,所有走子类重写的code方法 ,走过之后再回到父类中走没有走的代码

}
}

 

5)装饰设计模式

  就是使用被装饰类的一个子类的实例,在客户端jangle这个子类的实例交给装饰类。是继承的替代方案

 

public interface Phone {
  public abstract void call();
}

 

public class IPhone implements Phone {

@Override
public void call() {
  System.out.println("手机可以打电话了");
}

}

 

//抽象的手机装饰类

public abstract class PhoneDecorate implements Phone {

  private Phone p;

public PhoneDecorate(Phone p) {
  this.p = p;
}

@Override
public void call() {
  this.p.call();//PhoneDecorate中的call调用的是传过来的具体手机类的call
}
}

 

public class MusicPhoneDecorate extends PhoneDecorate {

public MusicPhoneDecorate(Phone p) {
  super(p);
}

@Override
public void call() {
  super.call();
  System.out.println("手机可以听音乐");
}
}

 

public class RingPhoneDecorate extends PhoneDecorate {

public RingPhoneDecorate(Phone p) {
  super(p);
}

@Override
public void call() {
  System.out.println("手机可以听彩铃");
  super.call();//这里的super指的是PhoneDecorate  调用PhoneDecorate中的call
}
}

 

public class PhoneDemo {
public static void main(String[] args) {
  Phone p = new IPhone();
  p.call();
  System.out.println("------------");

// 需求:我想在接电话前,听彩铃
  PhoneDecorate pd = new RingPhoneDecorate(p);
  pd.call();
  System.out.println("------------");

// 需求:我想在接电话后,听音乐
  pd = new MusicPhoneDecorate(p);
  pd.call();
  System.out.println("------------");

// 需求:我要想手机在接前听彩铃,接后听音乐
// 自己提供装饰类,在打电话前听彩铃,打电话后听音乐
  pd = new RingPhoneDecorate(new MusicPhoneDecorate(p));
  pd.call();
  System.out.println("----------");

 


// 我们在IO流中的使用
// InputStream is = System.in;
// InputStreamReader isr = new InputStreamReader(is);
// BufferedReader br = new BufferedReader(isr);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter((new OutputStreamWriter(
System.out)));

Scanner sc = new Scanner(System.in);
}
}

 

3、反射

  java反射机制是在运行状态中国,对于任意一个类,都能知道这个类的所有属性和方法;对于任意一个对象,都能调用它的以恶方法和属性。这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

 

  要想剖析一个类,首先要获取该类的字节码文件对象。

  获取Class类型的对象:

  1)Person p = new Person();

    Class c = p.getClass();

 

  2)Class c2 = Person.class();

 

  3)Class c3 = Class.forName("Person");

 

获取构造方法:

getConstructors: 
          返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。

getDeclaredConstructors 
          返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。

 

创建对象:

newInstance()
          创建此 Class 对象所表示的类的一个新实例。

 

invoke():

  public Object invoke(Object obj,Object... args)
  返回值是Object接收,第一个参数表示对象是谁,第二参数表示调用该方法的实际参数

 

获取所有成员:

getFields:
          返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段

getDeclaredField:
          返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。

 

获取单个成员:

getField

getDeclaredField

 

修改成员的值:

set(Object obj,Object value)

  将指定对象变量上此Filed对象表示的字段设置为指定的新值

 

获取所有方法:

getMethods

getDeclaredMethods

 

获取单个方法:

getMethod

getDeclaredMethod

 

暴力访问:

method.setAccessible(true)

 

举例:

public class Person {
private String name;
int age;
public String address;

public Person() {
}

private Person(String name) {
this.name = name;
}

Person(String name, int age) {
this.name = name;
this.age = age;
}

public Person(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}

public void show() {
System.out.println("show");
}

public void method(String s) {
System.out.println("method " + s);
}

public String getString(String s, int i) {
return s + "---" + i;
}

private void function() {
System.out.println("function");
}

@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", address=" + address
+ "]";
}

}

/*
* 通过反射获取构造方法并使用。
*/
public class ReflectDemo {
public static void main(String[] args) throws Exception {
// 获取字节码文件对象
Class c = Class.forName("cn.itcast_01.Person");

Constructor con = c.getConstructor();// 返回的是构造方法对象

// 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
Object obj = con.newInstance();
System.out.println(obj);
Person p = (Person)obj;
p.show();
}

 

public class ReflectDemo2 {
public static void main(String[] args) throws Exception {
// 获取字节码文件对象
Class c = Class.forName("cn.itcast_01.Person");

// 获取带参构造方法对象
  Constructor con = c.getConstructor(String.class, int.class,String.class);

// 通过带参构造方法对象创建对象
// public T newInstance(Object... initargs)
Object obj = con.newInstance(“xxx", 27, "北京");

System.out.println(obj);
}
}

//通过反射获取私有构造方法并使用

public class ReflectDemo3 {
public static void main(String[] args) throws Exception {
// 获取字节码文件对象
Class c = Class.forName("cn.itcast_01.Person");

// 获取私有构造方法对象
// NoSuchMethodException:没这个方法异常
// 原因是一开始我们使用的方法只能获取公共的,下面这种方式就可以了。
Constructor con = c.getDeclaredConstructor(String.class);

// 用该私有构造方法创建对象
// IllegalAccessException:非法的访问异常。
// 暴力访问
con.setAccessible(true);// 值为true则指示反射的对象在使用时应该取消Java语言访问检查。
Object obj = con.newInstance("xx");

System.out.println(obj);
}
}

 

 

给一个ArrayList<Integer>的一个对象,想向这个集合中添加一个字符串数据,如何实现??

//创建集合对象

ArrayList<Integer> array = new ArrayList<Integer>();

//array.add("hello");不行。因为类型不同,不能添加

 

//用反射实现

Class c = array.getClass();

Method m = c.getMethod("add",Object.class);

m.invoke(array,"hello");//调用array的add方法,传入的值是hello

syso(array);

posted on 2017-03-06 11:49  Mango虫子  阅读(282)  评论(0编辑  收藏  举报