Java培训总结笔记(四)

本文详细介绍了Java中的I/O操作,包括字节流、字符流、缓冲流、转换流及对象流,并通过示例代码展示每种流的具体应用。此外,还深入探讨了多线程的基本概念、创建与启动线程的方法、同步锁的作用及其应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.I/O补充内容

1.字节流
主要操作byte类型数据,以byte数组为准,一次读入或读出是8位二进制,主要操作类有字节输入流(InputStream)和字节输出流(OutputStream)两个抽象类,面向设备写入,无缓冲区。
代码示例:

    /**
     * 字节流读取文件
     * @throws IOException 
     */
    Private static void readTest() throws IOException {
        File file = new File("D:/java/file.txt");
        FileReader fr = new FileReader(file);
        System.out.println((char)fr.read());
        //返回的是ASCII码值
    }
    /**
     * 字节流读取文件
     * @throws IOException 
     */
    Private static void readTest() throws IOException {
        File file = new File("D:/java/file.txt");
        FileReader fr = new FileReader(file);
        char[] ch = new char[(int)file.length()];
        fr.read(ch);
        for(char c : ch){
            System.out.println(c);
        }
    }

2.字符流
主要操作字符类型数据,一次读入或读出是16位二进制,主要操作类有字符输入流(Reader)和字符输出流(Writer),面向缓冲区操作,可以用flush()方法。
代码示例:

    public static void writeTest() throws IOException{
        //创建文件
        File file = new File("D:/java/file.txt");
        //用字符流向文件写入内容
        FileWriter fw = new FileWriter(file);
        fw.write("Android");
        fw.flush();
        fw.close();
    }

3.缓冲流
缓冲流增强了读写文件的能力,避免一个一个地读写,会将内容先放置在内存中,有一定数据量时再进行操作。
代码示例:

    /**
     * 缓冲字符流读取操作
     * @throws IOException 
     */
    public static void bufferTest() throws IOException{
        File file = new File("D:/java/file.txt");
        FileReader fr = new FileReader(file);
        BufferedReader br = new BufferedReader(fr);
        System.out.println(br.readLine());
    }

4.转换流
转换流是字节流和字符流之间的桥梁,可对读取到的字节数据经过指定编码转换成字符,也可将读取到的字符数据经过指定编码转换成字节,一般用于将你创建的流直接转换为writer的流,写入字符或者字符串。
代码示例:

    /**
     * 转换流
     * @throws IOException 
     */
    public static void OutputStreamWriter() throws IOException{
        File file = new File("D:/java/file.txt");
        FileOutputStream fos = new FileOutputStream(file);
        OutputStreamWriter osw = new OutputStreamWriter(fos);
        osw.write("Android",0,7);//字符,偏移量,写入的长度。
        osw.flush();
        osw.close();
        }

5.对象流
用于写入对象的信息和读取对象的信息,将对象以文件的形式写入磁盘里保存起来。
代码示例:

    public static void ObjectText() throws IOException, ClassNotFoundException{
        Person p = new Person("宁静",250);
        File file = new File("D:/java/file.txt");
        /*
        FileOutputStream fos = new FileOutputStream(file);
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(p);
        oos.flush();
        oos.close();*/
        FileInputStream fis = new FileInputStream(file);
        ObjectInputStream ois = new ObjectInputStream(fis);
        Person person = (Person) ois.readObject();
        System.out.println(person);
    }

二.多线程

1.并发和并行
并发:在同一时刻,多件事情一定不是同时进行的。(轮流执行)
并行:在同一时刻,多件事情一定同时进行。
2.进程与线程的概念
进程:每个运行中的程序就是一个进程,Windows任务管理器上可以看到每一个进程,Linux下使用ps –e命令可以查看当前运行的所有进程。
线程:每个运行的程序(进程)内部可能会包含多个顺序执行流,每个执行流就可以看做线程。
3.创建并启动线程
创建线程的两种方式:
(1)继承Thread类

public class ThreadA extends Thread{
    public ThreadA(String name){
        super(name);
    }
    public void run(){
        for(int i=0;i<10;i++)
            System.out.println(getName() + "-->" + i);
    }
}

public class ThreadB extends Thread{
    public ThreadB(String name){
        super(name);
    }
    public void run(){
        for(int i=0;i<10;i++)
            System.out.println(getName() + "-->" + i);
    }
}

public class xiancheng {
    public static void main(String[] args){
        ThreadA tA = new ThreadA("线程A");
        ThreadB tB = new ThreadB("线程B");
        tA.start();
        tB.start();
    }
}

(2)创建ThreadTask类,实现runnable接口,重写run方法,代表线程要进行的任务

public class ThreadTask implements Runnable {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        for(int i=0;i<10;i++)
            System.out.println(Thread.currentThread().getName() + "-->" + i);
        }

}

public class xiancheng {
    public static void main(String[] args){
        ThreadTask task = new ThreadTask();
        Thread t = new Thread(task);
        t.start();
    }
}

启动线程:

//两线程执行同一个任务
public class ThreadTask implements Runnable {
    private int num = 0;
    private Object lock = new Object();//同步锁
    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(num<100){
            synchronized(lock)//同步代码块
            {
                num++;
                System.out.println(Thread.currentThread().getName() + "-->" + num);
            }
        }

    }
}

public class xiancheng {
    public static void main(String[] args){
        ThreadTask task = new ThreadTask();
        Thread t1 = new Thread(task,"线程A");
        Thread t2 = new Thread(task,"线程B");
        t1.start();
        t2.start();
    }
}

4.同步锁
即synchronized关键字,用来修饰一个方法或者一段代码块时,可保证同一时间只有一个线程执行该段代码。要注意:
(1)当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
(2)然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
(3)尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
(4)第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
(5)以上规则对其它对象锁同样适用。
5.线程的状态

  • 新建(new):新创建了一个线程对象。
  • 可运行(runnable):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权 。
  • 运行(running):可运行状态的线程获得了cpu 时间片(timeslice) ,执行程序代码。
  • 阻塞(block):阻塞状态是指线程因为某种原因放弃了cpu 使用权,即让出了cpu 时间片,暂时停止运行。直到线程进入可运行状态,才有机会再次获得cpu时间片转到运行状态。阻塞的情况有三种:
    -等待阻塞:运行的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。
    -同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。
    -其他阻塞:运行的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行状态。
  • 死亡(dead):线程run()方法和main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。
    这里写图片描述
华为java培训讲义 第一天 配置java环境变量: JAVA_HOME:配置JDK的目录 CLASSPATH:指定到哪里去找运行时需要用到的类代码(字节码) PATH:指定可执行程序的位置 LINUX系统(在" .bash_profile "下的环境变量设置) JAVA_HOME=/opt/jdk1.5.0_06 CLASSPATH=.:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar PATH=$PATH:$JAVA_HOME/bin:. export JAVA_HOME CLASSPATH PATH (将指定的环境变量声明为全局的) windows系统: 右击我的电脑-->属性-->高级-->环境变量 Java的运行过程: 编译:生成可执行文件,如C++中利用g++生成a.out,效率高,但不跨平台 解释:解释器把源文件逐行解释,跨平台但效率不高 在java中:先编译后解释,把.java文件编译成.class字节码文件 Java源代码文件(.java文件)---> Java编译器(javac)---> Java字节码文件(.class文件,平台无关的)---> Java解释器(java),执行Java字节码 Java的垃圾回收: 由一个后台线程gc进行垃圾回收 虚拟机判定内存不够的时候会中断代码的运行,这时候gc才进行垃圾回收 缺点:不能够精确的去回收内存 java.lang.System.gc(); 建议回收内存,但系统不一定回应,他会先去看内存是否够用,够用则不予理睬,不够用才会去进行垃圾回收 内存中什么算是垃圾: 不再被引用的对象(局部变量,没有指针指向的) java的安全性: 沙箱机制:只能做沙箱允许的操作 通过下面环节,实现安全 加载有用的类文件,不需要的不加载 校验字节码,查看允许的操作 查看代码和虚拟机的特性是否相符 查看代码是否有破坏性 查看是否有违规操作,如越界 查看类型是否匹配,类型转换是否能正确执行 源程序: package mypack; //相当于一个目录 public class HelloWorld{ public static void main(String[] args){ System.out.println(“Hello World”); } } 注: 1、文件名必须和public修饰的类名一致,以.java作为文件后缀,如果定义的类不是public的,则文件名与类名可以不同。 2、一个.java文件中可以有多个class,但是只有一个public修饰的类。 3、java源代码文件编译后,一个类对应生成一个.class文件 4、一个java应用程序应该包含一个main()方法,而且其签名是固定的,它是应用程序的入口方法,可以定义在任意一个类中,不一定是public修饰的类
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值