• day38 线程池,反射


    一、线程池

    线程池就是一个提前创建好的容器

    线程池技术就是一个可以复用线程的技术

    ②线程池的类

    jdk1.5提供了代表线程池的接口

    线程池的具体操作 5步

    建立线程池

    创建线程

    建立任务 

    提交任务

    关闭线程   

    建立任务的几种方法

    class MyTask implements Runnable  实现Runnable接口
    1. ExecutorService es = Executors.newFixedThreadPool(2);
    2. MyTask m1 = new MyTask("111");
    3. MyTask m2 = new MyTask("!!!");
    4. MyTask m3 = new MyTask("333");
    5. MyTask m4 = new MyTask("^^^");
    6. es.submit(m1,m2);
    7. es.submit(m3,m4);
    8. es.shutdown();
    class MyCallable implements Callable 
     实现Callable接口,好处是可以抛异常和有返回值 
    
    1. ExecutorService es = Executors.newFixedThreadPool(2);
    2. MyCallable m1 = new MyCallable("!!!");
    3. MyCallable m2 = new MyCallable("@@@");
    4. MyCallable m3 = new MyCallable("$$$");
    5. MyCallable m4 = new MyCallable("%%%");
    6. es.submit(m1);
    7. es.submit(m2);
    8. es.submit(m3);
    9. es.submit(m4);
    10. es.shutdown();

    线程池的底层原理

     new ThreadPoolExecutor(
     nThreads, -------> 核心线程数 2
     nThreads, -------> 最大线程数 5                            
     0L, -------------> 指定临时线程最大存活时间
     TimeUnit.MILLISECONDS,-->指定临时线程存活的时间单位(天 ,时 ,分 ,秒)
     new LinkedBlockingQueue(),--> 指定队列任务
     ThreadFactory threadfactort ,---->线程工厂 指定工厂创建线程 
     RejectedExecutionHandler handler );----->线程满且任务忙  此时新任务该如何处理
    
    1. ExecutorService es = new ThreadPoolExecutor(
    2. 3,
    3. 5,
    4. 7L,
    5. TimeUnit.MICROSECONDS,
    6. new LinkedBlockingQueue<>(2),
    7. Executors.defaultThreadFactory(),//使用创建新线程的默认工厂
    8. new ThreadPoolExecutor.AbortPolicy()//任务处理策略//如果有新任务拒绝处理
    9. );
    10. MyCallable n1 = new MyCallable("1");
    11. MyCallable n2 = new MyCallable("!");
    12. MyCallable n3 = new MyCallable("#");
    13. MyCallable n4 = new MyCallable("%");
    14. MyCallable n5 = new MyCallable("¥");
    15. MyCallable n6 = new MyCallable("……");
    16. MyCallable n7 = new MyCallable("a");
    17. MyCallable n8 = new MyCallable("b");
    18. MyCallable n9 = new MyCallable("c");
    19. MyCallable n10 = new MyCallable("d");
    20. es.submit(n1);
    21. es.submit(n2);
    22. es.submit(n3);
    23. es.submit(n4);
    24. es.submit(n5);
    25. es.submit(n6);
    26. es.submit(n7);
    27. es.submit(n8);
    28. es.submit(n9);
    29. es.submit(n10);
    30. es.shutdown();

    新任务拒绝策略
                   

     *  ThreadPoolExecutor.AbortPolicy    丢弃任务并抛出RejectedExecutionException异常
     *  ThreadPoolExecutor.DiscardPolicy  丢弃任务,但是不会抛出异常
     *  ThreadPoolExecutor.CallerRunsPolicy  由主线程负责调用任务的run方法从而绕过线程池来处理新任务
     *  ThreadPoolExecutor.DiscardOldestPolicy 抛弃队列中排队时间最久的任务,然后把当前任务加入到队列中

    线程池工作原理
     *  1. 线程池的核心组件是线程池管理器(ThreadPoolManager),它负责线程池的创建,销毁和任务调度等功能
     *      线程池管理器会根据传入的参数,创建一定数量的线程,并将这些线程放入到线程池中
     *
     *  2. 线程池中的线程是一种线程池线程(Pool Thread), 由线程池管理器维护,可以重用,线程池在线程
     *      执行任务之前,会反复从任务队列中获取任务并执行,当线程执行完成之后,会检查是否有新的任务需要执行
     *      如果没有,线程会等待新任务的到来
     *
     * 3. 线程池中的人物队列是一个有序的阻塞队列(Blocking Queue), 它用来保存等待执行的任务,当线程池线程获取
     *      任务时,会从队列中取出一个任务并执行,如果队列为空,线程池中的线程则进入等待状态,直到有新的任务加入
     *
     * 4. 线程池的优点:可以通过对线程的复用,减少创建和销毁线程的开销,提高系统的性能和资源的利用率,另外线程池还可以限制
     *    系统中同时执行的线程数量,防止系统资源被过量消耗
     *
     * 总结来说: 线程池的工作原理就是通过线程池管理创建一定数量的线程,并将这些线程放入线程池中,线程池中的
     * 线程会反复从任务队列中获取任务并执行,如果队列为空,线程会等待新任务的到来,通过这种方式,线程池可以提高
     * 系统的性能和资源的利用率

    二、反射

      获取一个类的类对象有三种方式


             *  方式一: 类名.class


             *      Class cls = String.class; //获取String的类对象
             *      Class cls = int.class; //获取int的类对象


             *  方式二: Class.forName(String className)


             *      class cls = Class.forName("java.lang.String");
             *      指定的参数为类的完全限定名: 格式:包名 + 类名


             *  方式三:使用ClassLoader类加载器完成

     *      ClassLoader scl = ClassLoader.getSystemClassLoader();
             *      Class aClass = scl.loadClass("java.lang.String");
             *      System.out.println(aClass);
             *


           
             *  方式四: 对象名.getClass()


             *       String str = "我是中国人";
             *       Class aClass = str.getClass();
             *       System.out.println(aClass);
             */

     反射类对象能调用的方法(注意类对象调用方法参数类型是类类型对象

            //创建类对象

        Class cls = Class.forName("com.oracle.pojo.Student");

              //创建类对象类的 对象

        /**
             * Class调用newInstance()方法创建实例是通过
             * 关联的Java类的无参构造创建的,如果对应的类
             * 没有无参构造会抛出异常
             */
            Student o = (Student) cls.newInstance();

               //想直接创建有参构造的对象使用constructor对象下的newInstance方法

              (注意方法参数是类对象

    1. Class aClass = Class.forName("com.oracle.pojo.Student");
    2. Constructor constructor = aClass.getConstructor(Integer.class, String.class, String.class);
    3. constructor.newInstance(1,"任可","襄阳");

            //全限定名


            String name = cls.getName();
            System.out.println(name);

            String simpleName = cls.getSimpleName();
            System.out.println(simpleName);  //类名

            //获取类的包名


            Package aPackage = cls.getPackage();
            System.out.println(aPackage);

            //获取父类的类对象


            Class superclass = cls.getSuperclass();
            System.out.println(superclass);

            //获取接口


            Class[] interfaces = cls.getInterfaces();
            for (Class anInterface : interfaces) {
                System.out.println(anInterface);
            }

            System.out.println("----------------------------");

            //获取所有的public修饰的属性,包括继承的


            Field[] fields = cls.getFields();
            for (Field field : fields) {
                System.out.println(field.getName());
            }

            //通过属性名获取


            Field id = cls.getField("id");
            System.out.println(id);

         

            //获取所有的自定义属性,


            Field[] files = cls.getDeclaredFields();
            for (Field file : files) {
                System.out.println(file.getName());
            }

            //通过属性名获取


            Field gender = cls.getDeclaredField("gender");
            System.out.println(gender);

      
            //获取属性的类型


            Field file = cls.getField("address");
            Class type = file.getType();
            System.out.println(type.getSimpleName());

            //获取属性的修饰符


            int i = file.getModifiers();
            String str = Modifier.toString(i);
            System.out.println(str);

            //给属性赋值


            Field id1 = cls.getField("id");
            id1.set(o,1);

            Field field = cls.getDeclaredField("name");
            System.out.println(field.getName());


            field.setAccessible(true); //强制获取权限


            field.set(o,"张三");//设置对象的属性

            Object o1 = id1.get(o);//获取对象的属性
            

            Object o2 = field.get(o);
            System.out.println(o2); //张三

            //获取类对象下的方法;

            调用方法(用该类的对象执行此方法)

            Class aClass = Class.forName("com.oracle.pojo.Person");
            Object o1 = aClass.newInstance();
            Person o = (Person) o1;
    
            Method say = aClass.getMethod("say");
            say.invoke(o);

                 

            //获取类对象下的有参的 public方法;

          用该类的对象加参数执行此方法(注意方法参数是类对象

    Class aClass = Class.forName("com.oracle.pojo.Person");
    Object o1 = aClass.newInstance();
    Person o = (Person) o1;
    Method say1 = aClass.getMethod("say", String.class);
    say1.invoke(o,"哈哈");

              //获取所有自定义的方法

    aClass.getDeclaredMethods()

                 //获取所有public方法

     aClass.getMethods();

                    //获取属性的修饰符

                    xxx.getMedifiers()

     三、终极练习

    自动执行与当前Test类在同一包下类所有无参方法

            //请说明如何通过反射获取和设置对象私有字段的值?

            //可以通过类对象的getDeclaredField()方法字段(Field)对象,然后再通过字段对象的setAccessible(true)将其设置为可以访问,接下来就可以通过get/set方法来获取/设置字段的值了。

    1. package com.oracle.pojo;
    2. import java.io.File;
    3. import java.lang.reflect.InvocationTargetException;
    4. import java.lang.reflect.Method;
    5. import java.lang.reflect.Modifier;
    6. import java.net.URISyntaxException;
    7. /**
    8. * 自动执行与当前类在同一包下类所有无参方法
    9. */
    10. public class Test {
    11. public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, URISyntaxException {
    12. //获取当前类所在路径
    13. File file = new File(Test.class.getResource(".").toURI());
    14. //获取当前路径下所有文件
    15. File[] files = file.listFiles();
    16. //判断是否为.class文件 获取文件名 substring()
    17. for (File file1 : files) {
    18. if (file1.getName().endsWith(".class")){
    19. String sb = file1.getName().substring(0,file1.getName().lastIndexOf("."));
    20. Class aClass = Class.forName("com.oracle.pojo."+sb);
    21. // Class aClass1 = Class.forName("com.oracle.pojo.Student");
    22. Object o = aClass.newInstance();
    23. Method[] declaredMethods = aClass.getDeclaredMethods();
    24. for (Method declaredMethod : declaredMethods) {
    25. if (declaredMethod.getParameterCount() == 0){
    26. if (declaredMethod.getModifiers() == Modifier.PUBLIC){
    27. declaredMethod.invoke(o);
    28. }else {
    29. declaredMethod.setAccessible(true);
    30. declaredMethod.invoke(o);
    31. }
    32. }
    33. }
    34. }
    35. }
    36. }

  • 相关阅读:
    【Verilog】HDLBits题解——Circuits/Basic Gates
    MySQL数据库的备份与恢复
    Hooks的使用
    Python二进制序列类型(二)array、struct和memoryview
    vue(二)
    Java基础进阶多线程-四种创建方式
    平衡二叉树的插入,删除以及平衡调整。
    数字化档案管理系统解决方案
    Mybatis-Plus:Sql 注⼊器、⾃动填充功能、逻辑删除
    idea一些常用的快捷键
  • 原文地址:https://blog.csdn.net/weixin_45939821/article/details/132823702