IO
Runtime对象的exec()方法可以运行其他程序,并产生一个Process对象。Process类提供3个方法
getErrorStream() 获取子进程错误流 getInputStream() 获取子进程输入流 getOutputStream() 获取子进程输出流
public static void main(String[] args) throws Exception { Process p = Runtime.getRuntime().exec("javac"); BufferedReader bf = new BufferedReader(new InputStreamReader(p.getErrorStream())); String b = null; while ((b = bf.readLine()) != null) { System.out.println(b); } bf.close(); }
RandomAccessFile 支持随机访问方式,既可以读,又可以写,如果想读写文件的一部分,应该用这个类
public static void insert(String filename, int pos, String content) throws Exception { File tmp = File.createTempFile("tmp", null); tmp.deleteOnExit(); RandomAccessFile raf = new RandomAccessFile(filename, "rw"); FileInputStream tmpi = new FileInputStream(tmp); FileOutputStream tmpo = new FileOutputStream(tmp); int hasRead = 0; raf.seek(pos); byte[] buf = new byte[64]; while ((hasRead = raf.read(buf)) > 0) { tmpo.write(buf, 0, hasRead); } raf.seek(pos); raf.write(content.getBytes()); while ((hasRead = tmpi.read(buf)) > 0) { raf.write(buf, 0, hasRead); } raf.close(); tmpi.close(); tmpo.close(); }
当一个可序列化的类有多个父类时,包括直接父类和间接父类,这些父类要么有无参构造器,要么也是可序列化的,如果父类不可序列化,只带无参构造器,父类定义的field不会序列化到二进制流中。
对象引用的序列化:如果类的field类型不是基本类型或String类型,而是引用类型,引用类必须可序列化,否则原类也不可序列化。
1 新io 采用内存映射文件的方式来处理输入输出,新io将文件或文件的一段区域映射到内存,这样可以像访问内存一样访问文件。
channel对传统输入输出的模拟,新系统中所有数据都要通过channel,通过他的map方法可以将一块数据映射到内存。传统输入输出面向流,新io面向块
2 buffer 像一个数组,保存多个类型相同的数据1 capacity 最大数据容量 2 limit 后的内容不能读写 3 position 下一开始读写的位置
读写过程 1 创建buffer position为0,limit为capacity 2 写入数据时,position后移 , 写完后 position为0,limit为position 3 开始读 , 读完后 position变为0,limit为capacity ,和刚创建一样。
CharBuffer buff = CharBuffer.allocate(8); System.out.println(buff.capacity()); 8 System.out.println(buff.limit()); 8 System.out.println(buff.position()); 0 buff.put('a'); buff.put('b'); buff.put('c'); System.out.println(buff.position());3 buff.flip(); System.out.println(buff.limit());3 System.out.println(buff.position());0 System.out.println(buff.get());a buff.clear(); System.out.println(buff.limit());8 System.out.println(buff.position());0 System.out.println(buff.get(2));c
3 channel类似与传统流对象,与传统流对象不同是, 1 可以直接将指定文件的全部或部分直接映射成buffer 2 程序不能直接访问channel中的数据,channel只能与buffer交互。 map将channel对应的部分或全部映射成bytebuffer , read write 用于与buffer交互
FileChannel inc = new FileInputStream("a.txt").getChannel(); FileChannel outc = new FileOutputStream("c.txt").getChannel(); MappedByteBuffer buff = inc.map(MapMode.READ_ONLY, 0, new File("a.txt").length()); outc.write(buff); buff.clear();
FileChannel f = new RandomAccessFile(new File("a.txt"), "rw").getChannel(); MappedByteBuffer buff = f.map(MapMode.READ_ONLY, 0, new File("a.txt").length()); f.position(new File("a.txt").length()); f.write(buff);
4 Charset 处理字节序列和字符序列之间的转换关系,还包含用于创建解码器和编码器的方法。
获得charset对象后,可以通过方法newDecoder, newEncoder方法分别返回charsetDecoder 和charsetEncoder对象,代表charset解码和编码器,通过decoder方法把bytebuffer字节序列转换成charbuffer字符序列,通过encoder将charbuffer将charbuffer或string转换成bytebuffer字节序列。
public static void main(String[] args) throws Exception { Charset c = Charset.forName("GBK"); CharsetEncoder newEncoder = c.newEncoder(); CharsetDecoder newDecoder = c.newDecoder(); CharBuffer buff = CharBuffer.allocate(8); buff.put("a"); buff.put("sdfs"); buff.flip(); ByteBuffer bf = newEncoder.encode(buff); System.out.println(newDecoder.decode(bf)); }
5 Java7 对io的改进 1 提供了全面的文件io和文件系统访问支持 2 基于异步channel的io
1 提供path接口 files,paths类 files 提供了文件复制,读取文件内容,写入文件内容的方法。
6 进程 :运行中的任务,具有一定独立功能,是系统进行资源分配和调度的独立单位。有3特性 : 1 独立性 有自己独立资源,有自己的地址空间,不允许访问其他进程地址空间 2 动态性 系统中活动的指令集合,有自己生命周期和各种不同状态,3 并发性 多进程在单处理器并发执行,之间不会相互影响。
线程是进程的组成部分,一个进程可以拥有多个线程,一个线程必须有一个符进程,线程拥有自己堆栈,程序计数器,局部变量,但不拥有系统资源,她与父进程其他线程共享进程的全部资源,编程简单。抢占式:当前运行的线程在任何时候都可能被挂起,以便另一个线程运行。
线程优点:1 进程不能共享内存,线程能共享内存 2 系统创建进程需要为进程重新分配内存,但创建线程代价小,效率高, 3 Java内置多线程功能支持,不是单纯地作为底层操作系统调度方式,简化多线程编程。
7 使用Calleable和Future创建线程
public class JDBCTest{ public static void main(String[] args) throws Exception { MyF m = new MyF(); FutureTask<Integer> f = new FutureTask<>(m); for (int i = 0; i < 100; i++) { if (i == 20) { new Thread(f).start(); } } System.out.println(f.get()); } } class MyF implements Callable<Integer> { @Override public Integer call() throws Exception { // TODO Auto-generated method stub int i; for (i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " " + i); } return i; } }
public class JDBCTest{ public static void main(String[] args) throws Exception { Accout a = new Accout("d",1000); new DrawThread(a, 800).start(); new DrawThread(a, 800).start(); } } class DrawThread extends Thread { private Accout accout; private double money; public DrawThread(Accout accout, double money) { super(); this.accout = accout; this.money = money; } @Override public void run() { // TODO Auto-generated method stub if (accout.getPrice() > money) { System.out.println("success " + money); accout.setPrice(accout.getPrice() - money); System.out.println("yu e" + accout.getPrice()); } else { System.out.println("error"); } } } class Accout { private String name; private double price; public Accout(String name, double price) { super(); this.name = name; this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } }
public class JDBCTest{ public static void main(String[] args) throws Exception { Accout a = new Accout("d",1000); new DrawThread(a, 800).start(); new DrawThread(a, 800).start(); } } class DrawThread extends Thread { private Accout accout; private double money; public DrawThread(Accout accout, double money) { super(); this.accout = accout; this.money = money; } @Override public void run() { synchronized (accout) { // TODO Auto-generated method stub if (accout.getPrice() > money) { System.out.println("success " + money); accout.setPrice(accout.getPrice() - money); System.out.println("yu e" + accout.getPrice()); } else { System.out.println("error"); } } } } class Accout { private String name; private double price; public Accout(String name, double price) { super(); this.name = name; this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } }
线程安全的类, 1 类的对象可以被多个线程安全访问, 2 每个线程调用对象的方法后会得到正确结果,并且对象状态保持合理状态。
public class JDBCTest{ public static void main(String[] args) throws Exception { Accout a = new Accout("d",1000); new DrawThread(a, 800).start(); new DrawThread(a, 800).start(); } } class DrawThread extends Thread { private Accout accout; private double money; public DrawThread(Accout accout, double money) { super(); this.accout = accout; this.money = money; } @Override public void run() { // TODO Auto-generated method stub accout.draw(money); } } class Accout { private String name; private double price; public Accout(String name, double price) { super(); this.name = name; this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public synchronized void draw(double money) { if (price > money) { System.out.println("success " + money); price -= money; System.out.println("yu e" + price); } else { System.out.println("error"); } } }
当两个线程相互等待对方释放同步监视器时,就会发生死锁
public class JDBCTest implements Runnable{ private A a = new A(); private B b = new B(); public void init() { Thread.currentThread().setName("zhu"); a.info(b); System.out.println("after zhu"); } @Override public void run() { // TODO Auto-generated method stub Thread.currentThread().setName("fu"); b.info(a); System.out.println("after fu"); } public static void main(String[] args) throws Exception { JDBCTest t = new JDBCTest(); new Thread(t).start(); t.init(); } } class A { public synchronized void info(B b) { System.out.println(Thread.currentThread().getName() + "进入实例A的info方法"); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "调用B的last方法"); b.last(); } public synchronized void last() { System.out.println(Thread.currentThread().getName() + "进入实例B的last方法"); } } class B{ public synchronized void info(A a) { System.out.println(Thread.currentThread().getName() + "进入实例B的info方法"); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "调用a的last方法"); a.last(); } public synchronized void last() { System.out.println(Thread.currentThread().getName() + "进入实例B的last方法"); } }
ThreadLocal 线程局部变量,为每一个使用变量的线程都提供一个变量值的副本,使每一个线程都可以独立改变自己的副本而不会和其他线程冲突,。当多个线程之间需要共享资源,达到线程之间通信功能,使用同步机制,如果仅仅需要隔离多个线程间共享冲突可以使用Threadlocal
public class JDBCTest extends Thread{ private Account a; public JDBCTest(Account a, String name) { super(name); this.a = a; } @Override public void run() { for (int i = 0; i < 10; i++) { if (i == 6) { a.setName(getName() + " " + i); } System.out.println(a.getName() + " " + i); } } public static void main(String[] args) throws Exception { Account a = new Account(); new JDBCTest(a, "jia").start();; new JDBCTest(a, "yi").start(); } } class Account { private ThreadLocal<String> name = new ThreadLocal<>(); public String getName() { return name.get(); } public void setName(String name) { this.name.set(name); } }