java基础知识总结(四)

本文主要介绍一下几个方面:
1.多线程
2.I/O
3.对象序列化
4.异常处理

1.多线程
线程是在一个进程中并发的一个顺序执行的流程。
线程的组成:
1.cup 有OS负责分配
2.Data 堆空间:存储对象(存储实例变量) 栈空间:存储局部变量。
3.Code 由程序员指定 继承Thread类或者实现Runnable接口。

实现方式:
1.继承Thread 一个Thread对象表示一个线程

eg:


class myThread extends Thread
{
    public void run() 
    {
        System.out.println("this is a test");
    }
}

2.实现Runnable接口
eg:

/**
 * 通过实现Runnable接口创建一个线程
 * @author DreamSea
 */
public class ThreadTest implements Runnable {
    public void run() {
            System.out.println("I'm running!");
    }
}

线程运行状态如下图:


thread.jpg

线程的状态:

新生状态(New): 当一个线程的实例被创建即使用new关键字和Thread类或其子类创建一个线程对象后,此时该线程处于新生(new)状态,处于新生状态的线程有自己的内存空间,但该线程并没有运行,此时线程还不是活着的(not alive);

就绪状态(Runnable): 通过调用线程实例的start()方法来启动线程使线程进入就绪状态(runnable);处于就绪状态的线程已经具备了运行条件,但还没有被分配到CPU即不一定会被立即执行,此时处于线程就绪队列,等待系统为其分配CPCU,等待状态并不是执行状态; 此时线程是活着的(alive);

运行状态(Running): 一旦获取CPU(被JVM选中),线程就进入运行(running)状态,线程的run()方法才开始被执行;在运行状态的线程执行自己的run()方法中的操作,直到调用其他的方法而终止、或者等待某种资源而阻塞、或者完成任务而死亡;如果在给定的时间片内没有执行结束,就会被系统给换下来回到线程的等待状态;此时线程是活着的(alive);

阻塞状态(Blocked):通过调用join()、sleep()、wait()或者资源被暂用使线程处于阻塞(blocked)状态;处于Blocking状态的线程仍然是活着的(alive)

死亡状态(Dead):当一个线程的run()方法运行完毕或被中断或被异常退出,该线程到达死亡(dead)状态。此时可能仍然存在一个该Thread的实例对象,当该Thready已经不可能在被作为一个可被独立执行的线程对待了,线程的独立的call stack已经被dissolved。一旦某一线程进入Dead状态,他就再也不能进入一个独立线程的生命周期了。对于一个处于Dead状态的线程调用start()方法,会出现一个运行期(runtime exception)的异常;处于Dead状态的线程不是活着的(not alive)。

在线程t1中调用t2.join() t1阻塞,当t2进入终止状态时,t1回到可运行状态。

线程同步:
当多线程并发访问临界资源(同一对象)时,如果破坏了原子操作(不可分割的操作),就会造成数据不一致。

//对o进行加锁的同步代码块
Synchronized(o)
{

}

任何对象都有一个互斥锁标记,用来分配给线程,只有拿到对象锁标记的线程,才能进入对该对象加锁的同步代码块。运行结束,线程进入同步代码块,释放锁标记
只用线程拿到对象的锁标记才能进入代码块。

锁池:任何对象都有一个空间,用来存放等待该对象锁标记的线程。

一个线程可以同时拥有多个对象锁标记,当线程阻塞在锁池中事,不会释放已拥有的锁标记,由此可能造成死锁。所以就有了线程间的通信。

线程间的通信:
任何对象都有一个等待队列,用来存放线程。
t1:o.wait(),必须放在对o加锁的同步代码块中,t1会释放它拥有的锁标记,同时t1阻塞在o的等待队列中。

t2:o.notify()/notifyAll(),必须放在对o加锁的同步代码块中,从o的等待队列中,释放一个或全部线程。

2.I/O
java.iO.File
File 对象,代表磁盘上的一个文件或者目录

File f = new File("F:\\file.text");

方法:
f.createNewFile():创建文件
f.delete():删除
f.mkdir():创建文件夹
f.exists():判断文件或目录是否存在
f.isDirectory():判断文件对象所代表的是否是目录
f.isFIle():是否是文件
f.getAbsolutePatyh():获得绝对路径

遍历:
eg:

        File file = new File("F:\\javaTest");
        File[] fs = file.listFiles();
        for (File file2 : fs) 
        {
         System.out.println("路径是:+"+file2.getAbsolutePath());   
        }
    

如果只想特殊后缀文件,如.zip
可以使FileFilter过滤文件
eg:

package test;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.nio.file.DirectoryStream.Filter;

public class ThreadFile {

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub

        File file = new File("F:\\javaTest");
        File[] fs = file.listFiles(new myFilter());
        for (File file2 : fs) 
        {
         System.out.println("路径是:+"+file2.getAbsolutePath());   
        }
    
}
}

class myFilter implements FileFilter
{
    public boolean accept(File f)
    {
        if (f.isDirectory())
        {
            return false;
        }
        else {
            
            if (f.getName().endsWith(".zip"))
            {
            return true;    
            }
            else {
                return false;
            }
        }
    }
}

另一种写法:
eg:

    File file = new File("F:\\javaTest");
        File[] fs = file.listFiles(new FileFilter() {
            
            @Override
            public boolean accept(File arg0) {
                // TODO Auto-generated method stub
                if (arg0.isDirectory())
                {
                    return true;
                }
                if (arg0.isFile())
                {
                    if (arg0.getName().endsWith(".zip"))
                    {
                        return true;
                    }
                }
                else
                {
                    return false;
                }
                return false;
                
            }
        });
        
        for (File file2 : fs)
        {
            if (file2.isFile())
            {
                System.out.println(file2.getAbsolutePath());
            }
            else {
                
                System.out.println(file2);
            }
        }

I/O流
流:对象,用来子啊JVM和外部数据员之间传输数据

按照不同的方面划分可以划分为不同的流
按照数据方向:输入流 / 输出流
按照数据的单位:字节流 / 字符流
按照流的功能:节点流 / 过滤流

字节流:以字节为单位,可以处理一切数据
字符流:以字符为单位,只能处理文本数据

节点流:实际传输数据的流
过滤流:给节点流增强功能

InputStream / OutputStream 字节流父类
FileInputStream / FileOutputStream 字节流实现类
创建输出流代码为:

    OutputStream os = new FileOutputStream("F:\\javaTest\2.text",true);

文件不存在会自动创建
true:表示文件存在会追加
false:会覆盖以前的文件

方法:

write(int a):把字节a写进去
write(byte[] bs):把字节数组bs全部写进去
write(byte[] bs,int off,int len):把字节数组的一段写出去,有off位置len个数

输出流FileInputStream
用于读取一个文件
eg:

InputStream input = new FileInputStream("2.text");
        while(true)
        {
            int i = input.read();
            if (i == -1)
            {
                break;
            }
            else {
                System.out.println((char)i);
            }
        }
    input.close();

int read():从文件中读取一个字节,返回-1结束
int read(byte[] bs):从文件中读取多个字节,bs:返回值为实际读到的字节数,以-1结束。
int read(byte[] bs,int off,int len):从文件中读的多个字节,放入bs中的一段,返回值为实际读到的字节数,以-1为结束。

过滤流:DataInputStream / DataOutputStream
过滤是为了增加节点流的功能,直接读写八种基本类型和字符串
(对字符串的读/写方法是reatUTF/writeUTF)
,eg:写入一个长整形

    
        OutputStream os = new FileOutputStream("1.text",true);
        DataOutputStream out = new DataOutputStream(os);
        out.writeLong(10000);
        out.close();

使用流读写文件一般分为四步:
1.创建节点流
2.封装过滤流
3.读 / 写 数据
4.关闭流

缓冲数据流(一般写文件时用的较多)
eg:

FileOutputStream fos = new FileOutputStream("1.txt");
        BufferedOutputStream out = new BufferedOutputStream(fos);
        out.write('a');
        out.flush();
        out.close();

PrintStream :写8种基本数据类型,缓冲。
RandomAccessFile:随机访问文件。

字符流
Reader/writer 字符流父类

FileReader / FileWriter 文件字符流,节点流。

BufferedReader / BufferedWrite(一般用Printwrite替代,采用默认编码方式) 缓冲流 过滤流。

InputStreamReader / PrintWriter 桥转换,把字节流转换为字符流。
在转换时指定编码方式。
eg:

    FileOutputStream fos = new FileOutputStream("1.txt");
        BufferedOutputStream out = new BufferedOutputStream(fos);
        Writer wir = new OutputStreamWriter(out, "GBK");
        
        wir.write('s');
        wir.close();

3.对象序列化
对象序列化:将对象通过流传输
ObjectOutputStream / ObjectInputStream
只有实现了Serializable接口的对象才能初始化。不仅对象本身需要实现Serializable接口,对象属性也需要实现该接口。用transient修饰的属性不参与序列化。
eg:对象XulieHuaTest

package test;

import java.io.Serializable;

public class XulieHuaTest implements Serializable{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    int age;
    String name;
    
    XulieHuaTest(int age,String name)
    {
        this.age=age;
        this.name = name;
    }

}

写入

FileOutputStream s = new FileOutputStream("1.text");
ObjectOutputStream os= new ObjectOutputStream(s);

XulieHuaTest one1 = new XulieHuaTest(20, "ss");
os.writeObject(one1);
os.close();

读取

FileInputStream r = new FileInputStream("1.text");
ObjectInputStream read = new ObjectInputStream(r);
XulieHuaTest sHuaTest = (XulieHuaTest)read.readObject();
System.out.println("age+"+sHuaTest.age+"+name+"+sHuaTest.name);
read.close();

4.异常处理
java中的异常处理有两种
1.throws 声明抛出 沿着调用链反向处理 属于消极处理。

public void testException() throws IOException
{
    //FileInputStream的构造函数会抛出FileNotFoundException
    FileInputStream fileIn = new FileInputStream("E:\\a.txt");
    
    int word;
    //read方法会抛出IOException
    while((word =  fileIn.read())!=-1) 
    {
        System.out.print((char)word);
    }
    //close方法会抛出IOException
    fileIn.clos
}

2.try...catch...finally 积极处理

public static void main(String[] args){
        try {
            foo();
        }catch(ArithmeticException ae) {
            System.out.println("处理异常");
            ae.printStackTrace();
        }
}
public static void foo(){
        int a = 5/0;  //异常抛出点
        System.out.println("这是一个测试!!");  //////////////////////不会执行
}

方法覆盖,抛异常的子类不能比父类抛出更多的异常。

你可能感兴趣的:(java基础知识总结(四))