自学javase的回顾(5/5)

自学javase的回顾(5/5)


javase部分完结,下个知识点:数据库

1、多线程

什么是多线程?(关键字:Thread)
一个程序叫做进程,程序能够同时做很多任务,同时运行很多任务叫做多线程。每一个任务就是一个线程。例如jvm处理源代码的时候,jvm就是一个进程,main方法和GC回收方法就是两个线程。
实现多线程的两种方法:
1、继承Thread,调用start方法,start方法是开辟了新的栈空间,新的栈空间和main方法栈是平级的:

public class Test {
    public static void main(String[] args) {
       MyThread t=new MyThread();
       t.start();
        for(int i=0;i<3;i++){
            System.out.println(i+"main");//0my 0main 1main 2main 1my 2my//运行结果每次都不同,因为每次线程抢夺的时间片可能不同
        }
    }
}
class MyThread extends Thread{
    public void run(){
        for(int i=0;i<3;i++){
            System.out.println(i+"my");
        }
    }
}

2、实现Runnable接口:

public class Test {
    public static void main(String[] args) {
       MyThread t=new MyThread();
       Thread thread=new Thread(t);
       thread.start();
        for(int i=0;i<3;i++){
            System.out.println(i+"main");//0my 0main 1my 1main 2my 2main
        }
    }
}
class MyThread implements Runnable{
    public void run(){
        for(int i=0;i<3;i++){
            System.out.println(i+"my");
        }
    }
}

线程的常用方法:
1、Thread.currentThread():获取当前线程
2、Thread.currentThread().getName()、setName():获取当前线程名字、设置当前线程名字
3、Thread.sleep():使当前线程休眠,单位毫秒
4、interrupt)():打断线程的休眠
5、stop():线程的终止,已过时,不建议使用,容易丢失数据。可以采用在run()函数中加判断等于true就运行,在main方法中写入等于false的语句来终止线程。
6、setPriority(int):设置线程的优先级,优先级最高10,最低1,默认优先级是5,优先级的高低跟执行顺序没关系,跟抢夺时间片的多少有关系,一般来说,优先级高的线程先执行完。
7、getPriority():获取线程的优先级。
8、yield():将线程的时间片让位给其他线程,但是这个操作需要时间,业务逻辑需求的代码谨慎使用。
9、join():当前线程进入阻塞状态,线程对象执行,直到线程对象结束,当前线程才可以执行。

线程同步:
1、同步编程模型:线程之间有等待关系,有安全性。但是效率低。
2、异步编程模型:线程之间没有等待关系,各自执行各自的。没有安全概念。

线程安全(关键字synchronized):
如果多个线程同时访问一个数据,就会发生数据的安全问题。这个时候就要用到同步编程模型。
1、synchronized (锁定的对象){代码块},灵活
2、synchronized 出现在实例方法上,一定锁的是this,不灵活
3、synchronized出现在静态方法上,锁的是类锁,即使创建再多对象,也是一把锁。

死锁:
两个线程之间互相锁住自己的对象,谁也不解锁自己的对象。所以尽量不要使用嵌套。

public class Test {
    public static void main(String[] args) throws InterruptedException {
        Object obj1=new Object();
        Object obj2=new Object();
       MyThread1 t1=new MyThread1(obj1,obj2);
       MyThread2 t2=new MyThread2(obj1,obj2);
       t1.start();
       t2.start();
        }
}
class MyThread1 extends Thread{
    Object obj1;
    Object obj2;
    public MyThread1(Object obj1,Object obj2){
        this.obj1=obj1;
        this.obj2=obj2;
    }
    @Override
    public void run(){
        synchronized (obj1){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (obj2){
            }
        }
    }
}
class MyThread2 extends Thread{
    Object obj1;
    Object obj2;
    public MyThread2(Object obj1,Object obj2){
        this.obj1=obj1;
        this.obj2=obj2;
    }
    @Override
    public void run() {
        synchronized (obj2){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (obj1){
            }
        }
    }
}

守护线程:
守护线程是伴随着用户线程并发的,一旦用户线程结束,守护线程必须结束。例如垃圾回收机制。
Thread.setDaemon(true):将线程转换为守护线程。

定时器(关键字:schedule):

public class Test {
    public static void main(String[] args) throws InterruptedException, ParseException {
        Timer t=new Timer();
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date first=sdf.parse("2020-07-05 13:05:00");
        t.schedule(new Task(0),first,1000);//1 2 3...
    }
}
class Task extends TimerTask{
    int i;
    public Task(int i) {
        this.i = i;
    }
    @Override
    public void run() {

        if(i>=0){
            i=i+1;
            System.out.println(i);
        }
    }
}

生成者和消费者模式(关键字:wait和notify,这两个方法不是线程的方法,是java对象的方法):
生产者和消费者模式就是生产数据到一个空间中,并且同时在这个空间消费数据,这就要求生产者和消费者之间必须平衡。

public class Test {
    public static void main(String[] args) {
        List list=new ArrayList();
        Thread t1=new Thread(new Producer(list));
        Thread t2=new Thread(new Coustomer(list));
        t1.setName("生产者线程");
        t2.setName("消费者线程");
        t1.start();
        t2.start();
    }
}
class Producer implements Runnable{

    private List list;

    public Producer(List list) {
        this.list = list;
    }

    @Override
    public void run() {
        while (true){
            synchronized (list){
                if(list.size()>0){
                    try {
                        list.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                Object obj=new Object();
                list.add(obj);
                System.out.println(Thread.currentThread().getName()+obj);
                list.notifyAll();
            }
        }
    }
}
class Coustomer implements Runnable{

    private List list;

    public Coustomer(List list) {
        this.list = list;
    }

    @Override
    public void run() {
        while (true){
            synchronized (list){
                if(list.size()==0){
                    try {
                        list.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }else{
                    Object obj=list.remove(0);
                    System.out.println(Thread.currentThread().getName()+obj);
                    list.notifyAll();
                }
            }
        }
    }
}

2、反射机制

什么是反射(关键字:reflect)?
通过反射可以去操作字节码文件。
获取类的字节码有三种方式:
1、Class c= Class.forName("");
2、引用对象.getClass();
3、Class c=任何类型.class

public class Test {
    public static void main(String[] args) {
        try {
            Class c=Class.forName("Person");//class Person
            System.out.println(c);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Person p=new Person();
        Class c1=p.getClass();
        Class c2=Person.class;
        System.out.println(c1);//class Person
        System.out.println(c2);//class Person
    }
}
class Person{
    String name;
}

类对象方法:
1、newInstance():调用类的无参构造方法。已过时,搭配Properties和IO流就可以灵活的实现类的调用。这样调用的好处是更改类只需要在properties配置文件中修改就可以。

public class Test {
    public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException {
        Properties p=new Properties();
        FileReader r=new FileReader("os.properties");
        p.load(r);
        String classname=p.getProperty("classname");
        Class c=Class.forName(classname);
        Object obj=c.newInstance();
        System.out.println(obj);//Person@4f3f5b24
    }
}
class Person{
    String name;
}

os.properties内容

classname=Person

2、getFields():获取类中所有公开的属性,返回一个Field[]
Field方法:Field.getModifiers:获取属性的类型,返回值是int类型,可以通过Modifiers.toString()转换
3、getDeclaredFields():获取类中所有属性,返回一个Field[]
3、getMethods():获取所有公开类的方法,返回一个Method[]
Method方法:Method.getReturnType().getSimpleName():获取方法返回值类型的名称
Method.getParameterTypes().getSimpleName():获取方法参数类型的名称
4、s.getDeclaredMethods():获取类中所有方法,返回一个Method[]
5、Method.invoke(实例):根据实例配置的参数去调用方法

番外:形式参数中的…
表示参数个数是不固定的,但是只能放在参数的最后面

public class ArgsTest {
    public static void main(String[] args) {
        c("asda",23,324);//c
        c1("asd","asd");//asd asd
    }
    public static void c(String v,int... args){
        System.out.println("c");
    }

    public static void c1(String... c) {
        for(int i=0;i<c.length;i++){
            System.out.println(c[i]);
        }
    }
}

3、注解

注解:
注释的一种,是一种引用数据类型,编译生成之后也是class文件
语法:[修饰符列表] @interface 注解类型名{}
注解怎么使用?用在什么地方?
注解的语法格式是@注解类型名
注解可以出现在类上、属性上、方法上、变量上等还可以出现上注解类型上
jdk中有哪些内置的注解:@Override父类重写的方法
@Override这个注解是给编译器参考的,如果不是父类重写的方法,编译器会报错
元注解:是标注注解的注解
常见的元注解:target、Retention
target是标注的注解只能出现在什么上
Retention是标注的注解最终保存到哪里
Deprecated这个注解标注的是已过时

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值