文件流和多线程
147.File类可以用绝对路径和相对路径和“.”表示,对于 绝对/相对 路径的 f/d,getName()返回的都是最后一级,但是对于getPath()/getPathFile(),绝对返回的是全路径,相对返回的是相对路径,就是file构造函数里填的路径,对于以“.”初始化的file来说,情况有点复杂,不记了,对于所有情况,getAbsoluteXxxx得到的都是据对路径,建议写相对路径,“。”对于不同的运行环境还不一样,Eclipse是当类所在的项目的根目录,其下有bin,src等,其他的还有变化,对于分割符File有一个常量separator来替换,如果什么都不写也是默认当前路径,"."和""是有区别的,用点初始化算一个文件夹,用“”它既不是文件夹也不是文件,好神奇,不能用listFile
148。getParent()返回父目录的路径名,绝对路径返回的从根目录开始到父目录结束,相对路径只有一级或用“.”构造的file,则返回null,renameTo,成功返回true,回把源文件弄没
149.文件检测相关的方法,存在,可读,可写,是文件,是夹,isAbsolute,是否是绝对路径,可以不用管平台差异,lastModified最后修改时间,length文件大小
150. 创建的是文件还是目录取决于你调用的是createNewFile还是mkdir,返回的是文件还是目录,就得用isFile和isDirectory来判断,不要根据名字判断,不准确
150.createNewFile()如果文件不存在,创建新文件,delete和deleteOnExit()删除和注册钩子删除,只能删空目录,当有多级的时候,只能从底层一点一点的删除,0mkdir/mkdirs创建文件夹,listRoots列出所有跟路径
151.文件过滤器,FilenameFilter是一个接口,用自己的类实现,当调用list方法时,传进去,来进行筛选
152.InputStream,OutputStream,Reader,Writer,是所有字节字符流的抽象基类,
153.FileInputStream和FileReader是文件输入流,FileOutputStream和FileWriter它们是文件输出流,这俩输出流的构造函数可以额外传入一个boolean值来指定是否追加。它们四个都是节点流,会和指定文件关联,它们不支持mark,FileIn/OutputStream 这俩货的基类就是InOutputStream,但是FileReader/Writer的基类却不是Reader/Writer,而是InputStreamReader/OutputStreamWriter,很神奇。
154.处理流是高级流,它的构造参数是其他节点流/低级流,而不是物理资源
155.ByteArrayInput/OutputStream, CharArrayReader/Writer,是用相应的数组来初始化的IO流,可以读写对应的数组,它们四个的close方法没有作用,也对,总不能关闭数组吧,它支持mark
157.BufferedInput/OutputStream,BufferedReader/Writer,它以另一个输入/输出流为构造函数,它提供对mark和reset的支持,BufferedReader/Writer还可按行读写。对于ReadLine()来说,它读到换行符为止,但返回的字符串不包含换行符,如果这一行只有换行符,返回“”,若到文件尾返回null,对于其他流来说,null意味着不可能再读到任何数据。
158,StringReader/StringWriter,是以一个String为参数初始化对象,然后对这个String进行读写,它也支持mark
159.PrintStream和PrintWriter,为其他输出类提供额外的,强大的功能,好多输出方法,它俩有两个特别之处,1.it will not throw IOException,2.when a byte array is written or println methods is invoked or a newline character or byte '\n' is written ,PrintStream will flush automatically, PrintWriter implements all of the print methods found in PrintStream. It does not contain methods for writing raw bytes, if automatic flushing is enabled it will be done only when one of the println, printf, or format methods is invoked, rather than whenever a newline character happens to be output. PrinterWriter内部包含一个BufferedWriter,就像是升级版的意思。其构造函数可以直接传入file或String,PrintStream的构造函数只能传OutputStream,而PrintWriter可传OutputStream和Writer,底层还是用转换流转换
160.InputStreamReader,OutputStreamWriter将字节流转换为字符流,构造函数就是传入一个字节流,但是转换完的Reader和Writer也不好用,所以再次包装成BufferedReader/Writer,此类能指定编码,给文本转码时能用上,
161.ObjectInputStream,ObjectOutputStream对象序列化时使用,高级流,可将对象转化为字节,反之也可以,类必须得先实现serializable接口,transient 关键字,用来阻止序列化某个成员变量,有个静态常量版本号,用来标记类结构是否发生变化,如果你不写,它有个隐式的,然后你每一次改类,隐式版本号都会变化,版本号不同会读取失败,如果你自己改了类结构,但是没有改自己定义的版本号,它就只还原以前有的成员变量,新的成员变量只写默认值。将一个对象转换为字节,叫做对象序列化,将这组字节写到硬盘上叫做对象持久化。
161.RandomAccessFile 任意文件访问,有两种模式rw读写和r只读,读写时文件不存在也会创建,只读时不存在会抛出FileNotFoundException
161.读写文件时,一字节的读非常慢,成块的读比较快,String 还能转成字节数组,默认用当前平台的字符集编码,也可以自己指定Charset进行编码,String构造函数也可一传入字节数组,同样用对的字符集进行解码,字符集的名字不区分大小写,常用的就是utf-8和gbk等等。
161.RandomAccessFile是非覆盖模式,如果已有,不删除源文件的内容,只是你写多少字节它就替换掉那些位置的多少字节,IO流有覆盖模式和追加模式,每次新建流,要是覆盖模式,则完全删除内容,重新写,追加顾名思义
161.字节流不支持读写文本文件,文本类的得用字符流
162.线程,三种方式,第一种,直接继承Thread类,方便快捷,但是缺点是不能再继承其他类,且,new Thread产生的新对象不能共用Thread类里面成员变量,第二种,Runnable接口,先写一个类,实现Runnable接口,填写里面run方法,然后用这个实现类新建一个对象,把这个对象当成参数来初始化多个新Thread实例,这样每个实例都会共用Thread里面的成员变量,且Thread还可以继承其他类。第三种,Callable和Future,先用一个类实现Callable<Integer>接口里面的call函数,泛型参数就是call函数的返回值,实现之后用这个类新建一个实例r,然后用FutureTask<Integer> t 把r当参数new一下,再用这个t来new一个Thread,运行完之后可以用t.get();来得到返回值,对于Runnable来说,如果thread共用一份runnable实例,那么线程也共用一个方法体,对于Callable来说,futuretask每新建一个,就可以得到一个返回值,
163.Callable对象不仅可以用FutureTask接,也可以用Future接,Callable对象的线程池写法有点操蛋,用线程池的submit方法来接callable实例,次方法会返回一个Future<E>对象,你接这个对象,然后调用get方法得到返回值。
163.如果你新建线程之后,没有调用start方法而是错误的调用了run方法,那么当你再次调用start方法会抛出异常,对新建的线程调用两次start,或对死亡的线程调用start,也会抛出异常,
164.线程新建之后,处于新建状态,此时它并没有表现出动态特征,和其他的变量没有什么区别,当调用start()方法之后,线程处于就绪状态,jvm会为其创建方法调用栈,就绪不会立即运行,值表示它已经准备好了,可以运行了,什么时候运行取决于jvm的调度,
165.当线程处于就绪、运行、阻塞时isAlive返回true,处于新建、死亡时,返回false,
166.线程有join,方法,调用其他线程的join就是等待其他线程运行完在继续,没啥特别的。
167.后台线程,调用Thread的setDaemon(true)方法来设置是前台还是后台,前台全部死亡后,后台自动死亡,还有一个isDeamon方法判断是否是后台,前台创建的子线程默认前台,后台默认后台,setDeamon方法必须调用在start之前,否则抛出异常,
168.sleep和yield,sleep移植性更好,还有其他的区别懒得写了
169.线程优先级有1~10级,但是并不是所有操作系统都能很好的对应这10级,所以用setPriority时尽量不要直接设置这10级,而是用Thread提供的3个静态常量,MAX_PRIOIRTY,MIN...和NORM_PRIORITY
170.synchronized同步代码块,类似与C#的lock,锁定一个引用变量,线程想要执行块里的代码,必须先获得对那个引用变量的锁定,同一时间,只有一个线程能获得锁定,也就是说不同线程之间只有一个能访问,但是同一个线程之间似乎可以随便访问,不会发生死锁。执行完代码块之后自动释放锁定,通常推荐把线程们访问的共享资源当作锁定对象。synchronized不能修饰构造器和属性。当在一个类里面的某个方法里写synchronized修饰的代码块时,可以用synchronized(this)这种写法。
171.当用synchronized修饰方法时,该方法就是同步方法,对象锁就是方法里的this。通过这种同步方法,可以实现线程安全类,把它可能被多个线程调用的方法用synchronized修饰,而不是所有方法,不可变类天生就是线程安全的,
178.下列几种情况会释放同步锁,块执行完了,或遇到return,break,异常等情况,终止了代码块,或获得锁定权限的自己调用了被锁对象的wait方法,
179.一下几种情况不会释放,调用sleep,yield,suspend和resume等
180.java1.5提供了Lock和ReadWriteLock两个跟接口,并提供了实现类,ReentrantLock(可重入锁),ReentrantReadWriteLock,用时,定义一个Lock对象,调用 对象.lock(),开始加锁,对象.unlock()释放锁,这期间执行代码,推荐用try finally来执行lock,确保,unlock一定被执行
181.死锁,当两个线程互相等待对方释放同步监视器时,就会出现死锁的现象,Thread.suspend方法非常容易出现死锁,java不建议你使用他,
182。Object的wait(),notify(),notifyAll()可以实现synchronized相关方法修饰的线程之间的通信,synchronized修饰的方法因为默认是当前类实例的this,所以可以直接调用这三货,但是synchronized修饰的代码块必须得调用被锁变量的这三方法,调用notify()方法之后其它线程不会立即唤醒,而是直到此线程调用wait方法,其他被唤醒的线程才会执行。三个线程换着运行: 对于o1来说运行完自己后该运行的代码后,先锁o2,再o2.notify()唤醒,释放o2锁,自己再等待o1.wait(),
183.线程池,java提供了一个工厂类Executors来管理线程池,该类提供了5个静态工厂方法来创建线程池,前三个返回了ExecutorService对象,该对象代表一个线程池,调用ExecutorService的execute方法,填加Runnable对象,填加完就开始执行了,调用shutdown()所有任务跑完了,结束所有线程,shutdownNow不等任务跑完,强行停止,如果线程正在阻塞,会引发InterruptedException。
184.BlockingQueue是Queue的子接口,但它主要作用不是为了当容器而是为了线程同步。相比于队列,它提供了两个额外的方法,put和take,这俩货天生自带阻塞功能,如果元素满了或元素空了,在调用put和take它会阻塞,直到条件符合为止,他也有普通的(add,remove,element)(不成功抛异常),(offer,poll,peek)(返回true,false),它有5个实现类,Array的和Linked的,其中Array的初始化时需要指定容量,一经创建,容量不可改变,而Linked可以不指定容量,默认用Integer.MAX_VALUE,
185.ThreadLocal<String> name;可以调用name.set 或 get方法来与其交互。感觉这个没卵用,主要就是提供多个互补相干的副本,一个线程一个,完全可以建多个变量,一个线程一个。




