(day19)阻塞队列、线程池、File类、递归

第一章 阻塞队列
    java.util.concurrent.BlockingQueue   阻塞队列顶层接口
        方法
            boolean add(E e);  有空间 添加成功 返回true 没空间抛异常  
            boolean offer(E e);   有空间 添加成功 返回true 没空间 返回false
            void put(E e);    有空间  添加成功 返回true  没空间等待
            E take();     获取元素  如果没有  等待
            
        常用实现类
            ArrayBlockingQueue
                有界
            LinkeBlockingQueue
                可选有界
            SynchronousQueue
                有界 一个元素都不存
        代码演示:
            public class Test03 {
                public static void main(String[] args) throws InterruptedException {
                    BlockingQueue<String> b = new ArrayBlockingQueue<>(3);

                    //有容量的情况下 用那个方法都可以
                    b.add("aaa");
                    b.offer("abc");
                    b.put("ccc");

                    System.out.println(b);
                    //满了后
                //  b.add("sss");  //抛异常
                    boolean b1 = b.offer("qqq");  //不抛异常返回false
                    System.out.println(b1);

                    //满了等待
                    //b.put("ee");
                    System.out.println("...");

                    //获取并移除
                    String take = b.take();
                    System.out.println(take);  // aaa
                    System.out.println(b.take());  // abc
                    System.out.println(b.take());  //  ccc
                    System.out.println(b);
                    //没有元素 等待
                    System.out.println(b.take());
                    System.out.println("game over");
                }
            }
            
第二章 线程池    
    概述
        创建线程每次都要和操作系统进行交互,线程执行完任务后就会销毁,
        如果频繁的大量去创建线程肯定会造成系统资源开销很大,降低程序的运行效率。
        
        线程池思想就很好的解决了频繁创建线程的问题,
        我们可以预先创建好一些线程,把他们放在一个容器中,需要线程执行任务的时候,从容器中取出线程,任务执行完毕后将线程在放回容器。
    
    使用线程池好处:    
        1. 降低资源消耗。通过重复利用已创建的线程降低线程创建、销毁线程造成的消耗。
        2. 提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
        3. 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,
        使用线程池可以进行统一的分配、调优和监控
    
    Executors线程池工具类
        作用: 快速创建线程池对象
        方法:
        static ExecutorService newFixedThreadPool(int nThreads);  创建一个可重用固定线程数的线程池。
        static ExecutorService newCachedThreadPool();   创建一个可根据需要创建新线程的线程池;
        static ExecutorService newSingleThreadExecutor();   创建一个使用单个 worker 线程的 Executor;
        static ScheduledExecutorService newScheduledThreadPool(int corePoolSize); 
                                                                    创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
    
    ExecutorService  线程池接口                                                            
        方法:
        Future<?> submit(Runnable task);     提交线程执行的任务,方法将返回null,因为run()方法没有返回值。
        <T>Future<T>submit(Callable<T> task);    提交线程执行的任务,返回Future接口对象。
        void shutdown();    关闭线程池,但是要等所有线程都完成任务后再关闭,但是不接收新任务。
        
    使用Callable完成异步计算
        Callable接口
        线程执行的任务接口,类似于Runnable接口。
            接口方法`public V call()throw Exception`
                线程要执行的任务方法
                比起run()方法,call()方法具有返回值,可以获取到线程执行的结果。
    
    代码演示:
        public class MyCall implements Callable<Integer> {

            private int num;

            public MyCall(int num) {
                this.num = num;
            }

            @Override
            public Integer call() throws Exception {
                int sum = 0;
                for (int i = 1; i <=num; i++) {
                    sum +=i ;
                }
                return sum;
            }
        }
        public class MyRun implements Runnable{
            private int i ;

            public MyRun(int i){
                this.i = i;
            }
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"执行了任务"+i);
            }
        }
        public class Test01 {
            public static void main(String[] args) throws ExecutionException, InterruptedException {
                ExecutorService pool = Executors.newFixedThreadPool(2);

                for (int i = 1; i <= 10 ; i++) {
                    pool.submit(new MyRun(i));
                }

                Future<Integer> submit = pool.submit(new MyCall(1000));
                Future<Integer> b = pool.submit(new MyCall(100));
                //获取call方法 返回的值
                System.out.println(submit.get());
                System.out.println(b.get());

                //执行完任务 然后关闭线程池
                pool.shutdown();
                //已提交的任务执行完 关闭线程池  未提交的任务就不执行了
                pool.shutdownNow();
            }
        }
        
    ThreadPoolExecutor
        我们可以使用ThreadPoolExecutor去创建线程池。
            ThreadPoolExecutor最完整的构造方法:
            public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler);
                              
        corePoolSize:    核心线程数量,线程池维护线程的最少数量
        maximumPoolSize:    线程池维护线程的最大数量
        keepAliveTime:    线程池除核心线程外的其他线程的最长空闲时间,超过该时间的空闲线程会被销毁
        unit:    keepAliveTime的单位,TimeUnit中的几个静态属性:NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS
        workQueue:    线程池所使用的任务缓冲队列
        threadFactory:    线程工厂,用于创建线程,一般用默认的即可
        handler:    线程池对拒绝任务的处理策略
    
    当线程池任务处理不过来的时候(什么时候认为处理不过来后面描述),可以通过handler指定的策略进行处理,ThreadPoolExecutor提供了四种策略:
        1. ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常;也是默认的处理方式。
        2. ThreadPoolExecutor.DiscardPolicy:丢弃任务,但是不抛出异常。
        3. ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
        4. ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务
    代码演示:
        public class Test {
            private static volatile boolean flag = true;

            public static void main(String[] args) throws InterruptedException {

                //此线程仅用于演示效果 可以让线程池中的线程任务快速执行完毕
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Scanner sc = new Scanner(System.in);
                        while (sc.hasNext()) {
                            String s = sc.nextLine();
                            if ("stop".equals(s)) {
                                flag = false;
                                break;
                            }
                        }
                    }
                }).start();

                //创建线程池
                ThreadPoolExecutor pool = new ThreadPoolExecutor(2,
                                                                3,
                                                                10,
                                                                TimeUnit.SECONDS,
                                                                new ArrayBlockingQueue<Runnable>(5),
                                                                // Executors.defaultThreadFactory(),
                                                                new ThreadPoolExecutor.AbortPolicy());
                
                //创建10个线程任务执行
                for (int i = 0; i < 10; i++) {
                    Thread.sleep(1000);
                    pool.execute(new MyRunnable((i + 1) + ""));

                }
            }

            static class MyRunnable implements Runnable {
                private String name;

                public MyRunnable(String name) {
                    this.name = name;
                }

                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + "执行任务" + name);

                    while (flag) {

                    }
                }
            }
        }
    
    
第三章 File类    
    3.1 概述
        java.io.File 类是文件和目录路径名的抽象表示,主要用于文件和目录的创建、查找和删除等操作。
        File类将文件,文件夹和路径封装成了对象,提供大量的方法来操作这些对象    
    3.2 File类的静态成员变量
        static String pathSeparator  与系统有关的路径分隔符。
            Window操作系统,分隔符是分号。
            Linux操作系统,分隔符是冒号。
        static String separator  与系统有关的默认名称分隔符。
            Window操作系统,名称分割符号为 \。
            Linux操作系统,名称分隔符号为 /。
            
        代码演示:
        //路径分隔符
        System.out.println(File.pathSeparator);  //win ;   linux   :
        //名称分隔符
        System.out.println(File.separator);    //  win  \    linux   /
        //写一个既可以在win运行 也可以在Linux上运行的通用路径
        String path2 = "work"+File.separator+"abc"+File.separator+"1.txt";
        System.out.println(path2);
        
    3.3 绝对路径和相对路径
        绝对路径:从盘符开始的路径,这是一个完整的路径,绝对路径具有唯一性。
        相对路径:相对于项目目录的路径,这是一个便捷的路径,开发中经常使用。    
        
        代码演示:
        String path = "d:\\aaa\bbb\ccc\a.txt";//带盘符 绝对路径
        String path2 = "a.txt"; //相对路径
        
    3.4 File的构造方法
        public File(String pathname);     根据给定的路径创建File对象
        File(String parent, String child);    根据给定的父路径  和子路径创建File对象
        File(File parent, String child);      File类型的父路径  字符串的子路径
        
        注意:
            1. File类的构造方法 不检测路径是否存在
            2. 注意Windows不区分大小写 
            3. 路径可以是文件  也可以是文件夹  但是只是创建对象
        代码演示:
            // 文件路径名
            String pathname = "D:\\aaa.txt";
            File file1 = new File(pathname); 
            System.out.println(file1);

            // 通过父路径和子路径字符串
            String parent = "d:\\aaa";
            String child = "bbb.txt";
            File file2 = new File(parent, child);
            System.out.println(file2);
    
            // 通过父级File对象和子路径字符串
            File parentDir = new File("d:\\aaa");
            String child = "bbb.txt";
            File file3 = new File(parentDir, child);
            System.out.println(file3);
        
    3.5 File类的获取方法 
        public String getAbsolutePath():  返回此File的绝对路径名字符串。
        public String getPath():  将此File转换为路径名字符串。 
        public String getName():  返回由此File表示的文件或目录的名称。  
        public long length():   返回由此File表示的文件的长度。 
        public File getParentFile():    返回由此File表示的文件或目录的父目录,如果没有父目录,返回null
        
        代码演示:
            File f = new File("d:/aaa/bbb.java");     
            System.out.println("文件绝对路径:"+f.getAbsolutePath());
            System.out.println("文件构造路径:"+f.getPath());
            System.out.println("文件名称:"+f.getName());
            System.out.println("文件长度:"+f.length()+"字节");
            System.out.ptintln("文件路径的父路径"+f.getParentFile());
        
    3.6 File类判断方法
        public boolean exists():        此File表示的文件或目录是否实际存在。
        public boolean isDirectory():  此File表示的是否为目录。
        public boolean isFile():        此File表示的是否为文件。
        
    代码演示:
    
        File file2 = new File("d:\\2development\\abc\\aa\\bb\\cc\\dd");
        //判断路径是否存在  存在返回true  不存在返回false
        boolean b = file2.exists();
        System.out.println(b);

        //判断是否是文件  是文件返回true  是文件夹返回false  路径不存在 返回false
        boolean b3 = file2.isFile();
        System.out.println(b2);


        if (file2.exists()){
            if (file2.isFile()){
                System.out.println("文件");
            }else{
                System.out.println("文件夹");
            }
        }else{
            System.out.println("路径不存在");
        }
        
    3.7 File类创建删除功能的方法 
        public boolean delete() :    删除由此File表示的文件或目录。  不进回收站,直接删除。
                                        如果删除的是文件 即使文件中有数据 也可以删除
                                        如果删除的是文件夹  必须是空文件夹 才能删除
            注意:
                    java删除是永久性删除 不走回收站
                    操作有风险  运行需谨慎
                    
    3.8 File类目录遍历方法
        public File[] listFiles(): 返回一个File数组,表示该File目录中的所有的子文件或目录
        
        
第四章 方法递归
    递归:指在当前方法内调用自己的这种现象
        public static void a(){
            a();
        }
    代码演示:
    public class Test01_File{
        public static void main(String[] args) {
            //递归计算1 - n的和
            int sum = getSum(100);
            System.out.println(sum);
            
            //递归求阶乘:所有小于及等于该数的正整数的积。
            int value = getValue(10);
            System.out.println(value);
            
            //遍历 D:\aaa 目录下的所有文件和所有的子目录。
            // 创建File对象
            File dir  = new File("D:\\aaa");
            // 调用打印目录方法
            printDir(dir);
        }
        
        public static int getSum(int n){
            if (n == 1){
                return 1;
            }else {
                return n +getSum(n-1);
            }
        }
        
        public static int getValue(int n){
            if (n == 1){
                return 1;
            }
                return n * getValue(n-1);
        }
        
        public static void printDir(File dir) {
            System.out.println(dir);
            // 获取子文件和目录
            File[] files = dir.listFiles();
            // 循环打印
            for (File file : files) {
                //判断是文件,直接输出
                if (file.isFile()) {
                    System.out.println(file);
                } else {
                    // 是目录,继续遍历,形成递归
                    printDir(file);    
                }
            }
        }
    }
        
        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值