Java 线程和反射---尚硅谷Java视频学习

  • 1.Java程序在运行得时候默认就会产生一个进程
  • 2.这个进程会有一个主线程
  • 3.代码都在主线程中执行

线程的生命周期

在这里插入图片描述

线程的执行方式

public class Java02_Thread {
    public static void main(String[] args) throws Exception {
        // TODO 线程 - 执行方式(串行,并发)
        // 串行执行:多个线程连接成串,然后按照顺序执行
        // 并发执行:多个线程是独立,谁抢到了CPU得执行权,谁就能执行

        MyThread1 t1 = new MyThread1();
        MyThread2 t2 = new MyThread2();
		
        t1.start();
        t2.start();

        // 将线程连接成串
        t1.join();
        t2.join(); //t1-t2

        System.out.println("main线程执行完毕");
    }
}
// TODO 第一个线程
class MyThread1 extends Thread {
    // 重写运行指令

    public void run() {
        System.out.println("MyThread-1 : " + Thread.currentThread().getName());
    }
}
// TODO 第二个线程
class MyThread2 extends Thread {
    // 重写运行指令

    public void run() {
        System.out.println("MyThread-2 : " + Thread.currentThread().getName());
    }
}

自定义线程

public class Java04_Thread_Run {
    public static void main(String[] args) throws Exception {

        // TODO 线程 - 运行

        MyThread3 t3 = new MyThread3();
        t3.start();

        MyThread4 t4 = new MyThread4();
        t4.start();

        MyThread5 t5 = new MyThread5("t5");
        MyThread5 t55 = new MyThread5("t55");

        t5.start();
        t55.start();


        System.out.println("main线程执行");
    }
}

// TODo 自定义线程
// 1. 继承线程类(父类)
// 2. 重写run方法
class MyThread3 extends Thread {
    @Override
    public void run() {
        System.out.println("t3 线程执行");
    }
}

class MyThread4 extends Thread {
    @Override
    public void run() {
        System.out.println("t4 线程执行");
    }
}

class MyThread5 extends Thread {
    private String threadName;

    public MyThread5(String name) {
        threadName = name;
    }

    @Override
    public void run() {
        System.out.println(threadName + " 线程执行");
    }
}

 // TODO 构建线程对象时,可以只把逻辑传递给这个对象
        //      传递逻辑时,需要遵循规则:() -> { 逻辑 }
        Thread t6 = new Thread(() -> {
            System.out.println("线程执行1");
        });

        t6.start();
// TODO 构建线程对象时,可以传递实现了Runnable接口得类得对象,一般使用匿名类
        Thread t8 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("线程执行");
            }
        });

        t8.start();

线程池

所谓得线程池,其实就是线程对象得容器
可以根据需要,在启动时,创建一个或者多个线程对象

        // Java种有4种比较常见得线程池
        // 1. 创建固定数量得线程对象
        //    ExecutorService是线程服务对象
        //ExecutorService executorService = Executors.newFixedThreadPool(3);
        // 2. 根据需求动态创建线程
        //ExecutorService executorService = Executors.newCachedThreadPool();
        // 3. 单一线程
        //ExecutorService executorService = Executors.newSingleThreadExecutor();
        // 4. 定时调度线程
        ExecutorService executorService = Executors.newScheduledThreadPool(3);



        for ( int i = 0; i < 5; i++ ) {
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName());
                }
            });
        }

线程同步

public class Java06_Thread_Syn {
    public static void main(String[] args) throws Exception {
        // synchronized - 同步关键字
        // 多个线程访问同步方法时,只能一个一个访问,同步操作
        // synchronized关键字还可以修饰代码块,称之为同步代码块
        /*
           synchronized( 用于同步得对象 ) {
               处理逻辑
           }

         */
        Num num = new Num();

        User user = new User(num);
        user.start();

        Bank bank = new Bank(num);
        bank.start();

    }
}
class Num {

}
class Bank extends Thread {
    private Num num;
    public Bank( Num num ) {
        this.num = num;
    }
    public void run() {
        synchronized (num) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("9:00, 开发,开始叫号");
            num.notifyAll();
        }
    }
}
class User extends Thread {
//    public synchronized void test() {
//
//    }
    private Num num;
    public User( Num num ) {
        this.num = num;
    }
    public void run() {

        synchronized ( num ) {
            System.out.println("我是号码1,银行还没开门,我需要等一会");
            try {
                num.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            System.out.println("叫到我得号了,该我办业务了。");
        }
    }

wait & sleep

    1. 名字
        wait : 等待
        sleep : 休眠
  • 2.从属关系
        wait : Object, 成员方法
        sleep : Thread, 静态方法
    1. 使用方式
        wait : 只能使用在同步代码中
        sleep : 可以在任意地方法使用
    1. 阻塞时间
       wait : 超时时间(会发生错误)
       sleep : 休眠时间(不会发生错误)
    1. 同步处理
       wait : 如果执行wait方法,那么其他线程有机会执行当前的同步操作。
       sleep : 如果执行sleep方法,那么其他线程没有机会执行当前的同步操作。

线程的安全问题

所谓的线程安全问题,其实就是多个线程在并发执行时,修改了共享内存中共享对象的属性,导致的数据冲突问题

public class Java07_Thread_Safe {
    public static void main(String[] args) throws Exception {
        User7 user = new User7();

        Thread t1 = new Thread(()->{
            user.name = "zhangsan";
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println(user.name);
        });
        Thread t2 = new Thread(()->{
            user.name = "lisi";
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println(user.name);
        });
        t1.start();
        t2.start();
        System.out.println("main线程执行完毕");
    }
}
class User7 {
    public String name;
}

在这里插入图片描述
栈内存是独享的,堆内存是共享的。两个线程访问同一个对象时,若对对象的属性进行修改,会引起冲突。

反射

  • 常用方法和操作
public class Java01_Reflect {
    public static void main(String[] args) throws Exception {
        // TODO 反射

        // 多态
        User user = new Child();
        user.test1();
        //user.test2();

        // 类对象
        Class<? extends User> aClass = user.getClass();

        // TODO 获取类的名称
        System.out.println(aClass.getName()); // 获取类的完整名称(包含包名)
        System.out.println(aClass.getSimpleName()); // 获取类的名称
        System.out.println(aClass.getPackageName()); // 获取类的包的名称

        // TODO 获取类的父类
        Class<?> superclass = aClass.getSuperclass();
        System.out.println(superclass);

        // TODO 获取类的接口
        Class<?>[] interfaces = aClass.getInterfaces();
        System.out.println(interfaces.length);

        // TODO 获取类的属性
        Field f = aClass.getField("xxxxx"); // public权限的属性
        Field f1 = aClass.getDeclaredField("xxxxx"); // 所有权限

        Field[] fields = aClass.getFields();// 所有public权限的属性
        Field[] declaredFields = aClass.getDeclaredFields(); // 所有权限

        // TODO 获取类的方法
        Method method = aClass.getMethod("test2");// public
        Method xxxx = aClass.getDeclaredMethod("xxxx"); // 所有权限

        Method[] methods = aClass.getMethods();// public
        Method[] declaredMethods = aClass.getDeclaredMethods(); // 所有权限

        // TODO 构造方法
        Constructor<? extends User> constructor = aClass.getConstructor();
        Constructor<?>[] constructors = aClass.getConstructors();
        aClass.getDeclaredConstructor();

        // TODO 获取权限(修饰符) :多个修饰符会融合成一个int值
        int modifiers = aClass.getModifiers();
        boolean aPrivate = Modifier.isPrivate(modifiers);
    }
}
class User {
    public void test1() {
        System.out.println("test1...");
    }
}
class Child extends User {
    public void test2() {
        System.out.println("test2...");
    }
}
  • 类加载器
    Java种的类主要分为3种:
  • Java核心类库种的类:String, Object
  • JVM 软件平台开发商
  • 自己写的类,User, Child
    类加载器也有3种:
    1. BootClassLoader : 启动类加载器(加载类时,采用操作系统平台语言实现)
    1. PlatformClassLoader :平台类加载器
    1. AppClassLoader : 应用类加载器
public class Java02_Reflect_ClassLoader {
    public static void main(String[] args) throws Exception
        // TODo 获取类的信息
        Class<Student> studentClass = Student.class;
        // 获取类的加载器对象
        ClassLoader classLoader = studentClass.getClassLoader();
        System.out.println(classLoader);
        System.out.println(classLoader.getParent());
        System.out.println(classLoader.getParent().getParent());

        Class<String> stringClass = String.class;
        // 获取类的加载器对象
        ClassLoader classLoader1 = stringClass.getClassLoader();
        System.out.println(classLoader1);

        // 加载Java核心类库 > 平台类库 > 自己类
    }
}
class Student {

}

使用反射实现登录功能

public class Java03_Reflect_Test {
    public static void main(String[] args) throws Exception {

        // TODO 反射 - 练习
        // 员工的登录功能,

        // 构造方法对象
        Class empClass = Emp.class;
        Constructor declaredConstructor = empClass.getDeclaredConstructor();
        // 构建对象
        Object emp = declaredConstructor.newInstance();

        // 获取对象的属性
        Field account = empClass.getField("account");
        Field password = empClass.getField("password");

        // 给属性赋值
        account.set(emp, "admin");
        password.set(emp, "admin");

        // 获取登录方法
        Method login = empClass.getMethod("login");

        // 调用方法
        Object result = login.invoke(emp);

        System.out.println(result);
    }
}
// 员工
class Emp {
    public String account;
    public String password;

    public boolean login() {
        if ( "admin".equals(account) && "admin".equals(password) ) {
            return true;
        } else {
            return false;
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值