Java回顾3【笔记】

1. 多线程

实现多线程的两种方式,注意,只有start()方法才是启动线程
	一、创建一个类继承Thread类并重写run方法,创建该类的对象.start();启动线程
	二、类实现Runnable重写run方法,将该类作为参数放在Thread类中.start();启动线程
例子:
	new My().start();//My是我创建的类继承了Thread
	Runnable r = () -> System.out.println("Runnable:" + Thread.currentThread());
	new Thread(r).start();//启动Runnable的线程
	System.out.println("Main:" + Thread.currentThread());//主方法的线程

输出结果:
	Extends:Thread[Thread-0,5,main]
	Main:Thread[main,5,main]
	Runnable:Thread[Thread-1,5,main]

线程安全问题,需加锁:同步代码块、同步方法
同步代码块:synchronized(锁对象){}
	锁对象的选择:可以是任意类型的对象,只要几个线程是用的同一个对象即可,this也行,自己创建一个静态对象也行
		      但是继承Thread的类创建多个线程不能用this,因为此时创建了好几个Thread对象,不是同一个
	锁的范围:锁的范围很重要,具体问题具体分析
同步方法:public synchronized void test(){}
	锁对象不是我们来选择的:
		非静态方法:this(所以不适用继承)
		静态方法:当前类的Class对象
死锁:博客里有

常用API:
	Thread.sleep(500);//当前线程睡一会儿
	Thread.currentThread();//获取当前线程对象
	getName()//线程名称

	interrupt():当某个线程在sleep的时候,将其敲醒,会触发异常
	join():指代被哪个线程join,例如写在main方法中,是指xx.join(),main等xx执行完再执行,是main被阻塞了。
	yield():暂停,直接回到就绪状态而不是阻塞,然后也会参加下一次调度

生产者与消费者问题
	就是一个生产一个消费。当生产足够的时候就wait(),消费至0的时候也wait()
	wait()之后一旦可以继续生产或者消费了就需要notify()唤醒。
	如果你是消费者,notify()可能还是会唤醒消费者,这样就卡死了。所以需要用notifyAll(),全部唤醒

	注意:这几个方法都必须由同步锁对象调用

	只有wait()和join()方法会释放锁,join的底层是wait实现的。

2. 反射

        //反射
        //两种方式都能获取到
        Class<?> oo = Class.forName("hello.Order");
        Class<Order> o = Order.class;

        //我只列举了这几个,从上往下从左往右的顺序排列
        System.out.println("包名:" + oo.getPackage());
        System.out.println("注解:" + o.getAnnotations().length);
        //getDeclaredXXX() 与 getXXX()的区别
        //getDeclaredXXX():private的可以获取到
        //getXXX():继承的可以获取到

        System.out.println("修饰符: 数字:" + o.getModifiers() + " 名字:" + Modifier.toString(o.getModifiers()));
        System.out.println("类名:" + o.getName());
        System.out.println("父类:" + o.getSuperclass());
        System.out.println("接口:" + o.getInterfaces().length);

        System.out.println("属性:" + o.getDeclaredFields().length);
        System.out.println("构造器:" + o.getConstructors().length);
        System.out.println("方法:" + o.getDeclaredMethods().length);
        //后面有加length的都是数组对象,需要单独去遍历
        //当然有很多方法都是有参的,也就是可以直接选定某个东西
        //例如:o.getDeclaredField("id"),就直接拿到了id这个属性

            //属性的类型 getType()
            Field[] fields = o.getDeclaredFields();
            System.out.println("属性的类型:" + fields[0].getType());
            //构造器/方法的形参 getParameterTypes()
            Constructor<?>[] constructors = o.getConstructors();
            System.out.println("构造器形参:" + constructors[1].getParameterTypes().length);


        //操作篇:
        //创建对象
        Order order = o.newInstance();//直接创建
        Object o1 = o.getConstructors()[0].newInstance();//构造器创建
        Object o2 = o.getConstructor(Integer.class).newInstance(2);//有参构造器创建

        //给属性赋值(创建对象后的基础上)
        Field id = o.getDeclaredField("id");
        id.setAccessible(true);//private 也可以赋值
        id.set(order, 5);

        //调用方法(创建对象后的基础上)
        Method setType = o.getDeclaredMethod("setType", String.class);//方法名, 形参列表
        setType.invoke(order, "hello");
        System.out.println("id:" + order.getId() + " type:" + order.getType());

3. IO

File类
    //递归列出所有文件
    public static void listAllSub(File dir){
        if(dir.isDirectory()){// isDirectory()
            File[] listFiles = dir.listFiles();// listFiles()
            for(File f : listFiles){
                listAllSub(f);
            }
        }
        System.out.println(dir);
    }

    //递归获取文件大小
    public static long getSize(File file){
        if(file.isFile()){// isFile() 不用判断也行,和其他方法一样
            return file.length();
        }else if(file.isDirectory()){
            long sum = 0;
            File[] files = file.listFiles();
            for(File f : files){
                sum += getSize(f);
            }
            return sum;
        }
        return 0;
    }

    //递归删除
    public static void deleteDir(File file){
        if(file.isDirectory()){
            File[] files = file.listFiles();
            for(File f : files){
                deleteDir(f);
            }
        }
        file.delete();
    }

public static void main(String[] args) {
        File file = new File("D:\\LearningData\\Code\\GitTest\\recording");
        listAllSub(file);
        System.out.println(getSize(file));
        //过滤器,接受
        File[] filter = file.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return pathname.getName().endsWith(".txt") && pathname.getName().contains("test");
            }
        });
        for(File f : filter){
            System.out.println(f);
        }
    }

超类:
InputStream/OutputStream/Reader/Writer
一般用用的:File~
缓冲:Buffered~
转换:InputStreamReader/OutputStreamWriter,其实相当于组合了一下

public static void main(String[] args) throws Exception {
        FileReader fileReader = new FileReader("1.txt");
        readFile(fileReader);

    }

    public static void readFile(FileReader fileReader) throws IOException {
        char[] arr = new char[10];
        int len;
        while((len = fileReader.read(arr)) != -1){// read(char[] arr)将内容存在char[]中并且给长度,长度为-1则为空
            System.out.print(new String(arr, 0, len));
        }
        fileReader.close();
    }

FileWriter也new一个对象存放内容,然后在while循环里用write()方法将arr写进去

记住,当用到装饰者模式的时候,close()时要先脱外衣,再脱内衣,也就是将装饰的一层外衣先脱掉

FileInputStream/FileOutputStream用法与FileReader/FileWriter相同只是char[]要改为byte[],而且因为是byte可能会出现乱码,我在new String()后面加一个参数"utf-8"也不能很好解决
所以可以用InputStreamReader(fileInputStream,"utf-8"),装饰者模式,用这个对象的时候又得将byte改为char,其实就是变成Reader吧????
当然也有OutputStreamWriter(这两个应该最奇葩,是将超类组合了一下)

BufferdReader
public static void main(String[] args) throws Exception {
        FileReader fileReader = new FileReader("1.txt");
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        buffReadFile(bufferedReader);
        fileReader.close();
    }

    public static void buffReadFile(BufferedReader bufferedReader) throws IOException {
        while(bufferedReader.ready()){// read()方法
            System.out.println(bufferedReader.readLine());// readLine()读取整行
        }
        bufferedReader.close();
    }

我原以为BufferdInputStream也有readLine()方法,就可以很容易的解决乱码问题,原来没有!
posted @ 2021-04-15 10:50  lwxx  阅读(61)  评论(0)    收藏  举报