线程

来源:互联网 发布:centos怎么退出vi 编辑:程序博客网 时间:2024/05/22 20:22

进程和线程概念

  • 进程:相对于系统来讲(Win Linux Mac),独立的内存空间,并发性,动态性
  • 线程:相对于进程来讲,是进程内部的一个执行单元,内部单一的执行单元,顺序控制流程,共享进程资源

创建线程

  • 1.继承Thread类,复写其run()方法,调用start()方法,启动线程
MyThread  t = new MyThread ();t.start();
  • 2.实现Runnable接口,实现其run()方法,调用start()方法
MyThread mt =   new MyThread ();Thread t  =   new Thread(mt);t.start();

两种创建进程方法的比较

继承Thread类方式的多线程
- 优势:编写简单
- 劣势:无法继承其它父类

实现Runnable接口方式的多线程
- 优势:可以继承其它类,多线程可共享同一个Thread对象
- 劣势:编程方式稍微复杂,如果需要访问当前线程,需要调用Thread.currentThread()方法

调用start()方法启动线程和直接调用run()方法的区别

  • 调用start()方法,会申请新的线程,开辟新的线程空间去执行run()方法中的内容
  • 调用run()方法,只是由当前线程去调用run()方法,不会创建新的线程,仅将其当成一个普通方法调用

多线程的优势(重点)

  • 多线程使系统空转时间减少,提高CPU利用率
  • 进程间不能共享内存,但线程之间共享内存非常容易
  • 使用多线程实现多任务并发比多进程的效率高
  • Java语言内置多线程功能支持,简化了Java的多线程编程

线程状态

这里写图片描述

  • 新生 创建新的线程对象
  • 运行 调用start()方法
  • 阻塞
    1.sleep(long time) 睡眠time毫秒后,自动唤醒继续运行
    2.join()加入 A线程加入到B线程,B线程等待A线程运行完毕再继续向下执行
    3.yield()暂停瞬间,然后继续执行
  • 死亡 整个线程的run()方法的代码块运行完毕

线程锁

  • synchronization(){ }同步代码块 多个线程中存在使用同一把锁的代码块,多个线程会抢这一把锁,抢到的进入同步代码块,剩下的线程全在外面阻塞,阻塞到进入的线程运行完,该线程会释放锁,所有阻塞的线程继续开始抢锁。
  • 同步方法 public synchronized void xxx (){ },同步方法的锁,就是锁住的对象就是调用该方法的对象
  • 注意 :在拥有同步方法的类中,锁住的是该类的实例化的对象

线程同步的必要性

这里写图片描述

线程间通信

  • wait()和notify()
  • 当执行了wait()方法后,本线程终止,将锁释放给正在等待该锁的线程
  • 当执行了notify()方法后,线程会唤醒正在等待该锁的对象,但是唤醒后不是立即执行,而是等调用notify()方法的线程执行完同步代码块之后,才开始抢占执行。

Timer

  • 定时器的使用
    • 首先要实例化Timer对象,
    • 然后要重写一个类继承TimerTask类,在复写其中的run()方法
    • 然后调用Timer()对象的schedule(TimerTask task, long delay, long period)
    • 第一个参数是继承TimerTask类的实例化对象
    • 第二个参数是延时多久开始执行其run()方法
    • 第三个参数是run()方法循环的间隔时间
public class Test {    public static void main(String[] args) {        Timer timer=new Timer();        timer.schedule(new MyTimerTask(), 2000 ,500);    }}public class MyTimerTask extends TimerTask{    private int i=0;    public void run() {        System.out.println("正在计时:"+i++);    }}

反射详解

  • 反射就是可以通过对象实例或者类名来获取Class对象,通过Class对象的各种方法,可以获得该类的各种信息,包括属性,方法,构造器,返回值类型,属性类型等等。
  • Class 类的抽象 Person Dog Car
    Field 属性的抽象
    Method 方法的抽象
    Constructor 构造器的抽象

这里写图片描述

  • 可以通过反射的机制,给对象中的属性进行赋值操作
public class ReflectionTest {    public static void main(String[] args) {        Person zhangsan=new Person();        System.out.println(zhangsan.getName());        //此Person中不存在一个可以访问方法去修改名字        //可以使用反射去修改zhangsan这个对象的name        //1得到Person的Class对象        Class<Person> zhangsanClass=(Class<Person>) zhangsan.getClass();        try {            //2得到Person类中名称是name的字段            Field name=zhangsanClass.getDeclaredField("name");            //3取消反射时的java语言访问限制            name.setAccessible(true);            //4使用field修改zhangsan的name的值,因为Person中的name是private的,所以会报错,其他修饰符的话不会报错            name.set(zhangsan, "张三");            //5重新打开反射时的java语言访问限制,以后访问还要检查            name.setAccessible(false);            System.out.println(zhangsan.getName());        } catch (SecurityException e) {            e.printStackTrace();        } catch (NoSuchFieldException e) {            e.printStackTrace();        } catch (IllegalArgumentException e) {            e.printStackTrace();        } catch (IllegalAccessException e) {            e.printStackTrace();        }    }}public class Person {    private String name ;//zheshishenme a     private String sex;    public String getName() {        return name;    }    public String getSex() {        return sex;    }    public void setSex(String sex) {        this.sex = sex;    }}

设计模式

Dao模式
  • 只有属性和set get方法

单例模式

  • 在要单例化的类中
    • ① 私有化构造器,不允许外部使用new关键字创建对象
    • ② 声明一个静态的私有的Person对象
    • ③ 提供一个静态的公有的同步方法供外部访问,返回值类型是该类 为什么使用synchroized防止多个线程同时访问这个方法 静态同步方法的锁是指的类本身
    • ④ 在该方法中添加限制
public class Person {    private String name;    private String sex;    //创建一个静态的私有的该类对象,声明为静态只能有一个这个对象的实例    private static Person person;    //私有化构造器    private Person() {    }    //创建一个共有的静态的同步方法,声明为同步方法可以限制多个线程同时访问的问题,声明为静态可以通过类名调用    public synchronized static Person newInstance() {        //在其中添加限制,若不为空,就实例化对象,否则仅返回其对象        if (person==null) {            person=new Person();        }        return person;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getSex() {        return sex;    }    public void setSex(String sex) {        this.sex = sex;    }}public class Test {    //所有输出的内容hashcode是一样的,表示是同一个对象    public static void main(String[] args) {        Person zhangsan=Person.newInstance();        System.out.println(zhangsan);        Person lisi=Person.newInstance();        System.out.println(lisi);        new Thread(new Runnable() {            public void run() {                Person wangwu=Person.newInstance();                System.out.println(wangwu);            }        }).start();        new Thread(new Runnable() {            public void run() {                Person zhaoliu=Person.newInstance();                System.out.println(zhaoliu);            }        }).start();    }}

简单工厂模式

  • 创建一个工厂,使用这个工厂创建这个类的对象
  • 创建一个配置文件properties格式,用Properties类从中读取类的信息,根据类的信息用Class的forName(String str),获取累的对象,
  • 再用该对象实例化要生成的对象实例
  • 要改变生成的对象实例时候,就不用重新编译代码,仅仅修改配置文件的类的信息就可以了
  • 另外如果要扩展程序的话,对源代码基本不用改变,直接生成你要添加的类的代码即可
public class Person {    public void speak() {        System.out.println("人类会说话");    }}public class Teacher extends Person{    @Override    public void speak() {        System.out.println("老师会讲课");    }}public class PersonFactory {    public Person newInstance() {        Person person=null;        Properties pro=new Properties();        try {            //解析配置文件            pro.load(new FileInputStream("config.properties"));            //从配置文件中读取类的信息            String str=pro.getProperty("classname");            //Class类根据类名生成Class的对象            Class name=Class.forName(str);            //由Class对象生成对应类的实例            person=(Person) name.newInstance();        } catch (FileNotFoundException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (ClassNotFoundException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (InstantiationException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (IllegalAccessException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        return person;    }}public class Test {    public static void main(String[] args) {        PersonFactory factory=new PersonFactory();        Person person=factory.newInstance();        //根据生成对象的不同,输出相应改变        person.speak();    }}
  • 配置文件如下
  • 这里写图片描述

知识漏洞

static

  • 在一个类中,static修饰的类的属性,不管实例化多少个对象,该属性都只有一个,并且对每一个实例化对象共享。

PrintWriter

print()和println()的区别
- print()仅仅是打印输出
- println()打印输出,并且终止当前行的输出

0 0