泛型
- 泛型是JDK1.5提出的
- 泛型类型必须是类,不能是基本数据类型
-
List
、List 如果一个泛型类中需要传递一个List
- 如果List
能作为List 的父类 - 创建一个List
或List 存放到List 中 - 那么用get获取数据时,获取到的是Integer、float还是Number类型的,如果是这样还要进行类型转化
- 这违背了定义泛型的初衷
- 所以List
和List 不看做有父子关系
那么如果我们需要获取不同类型的数据,难道需要编写获取不同类型的方法吗?这违背了多态的特性
类型通配符<?>可以很好的解决这个问题
public static void getData(Box<?> data) {System.out.println("data :" + data.getData());}
也可以通过<? extends Number> 与 <? super Number> 控制类型通配符的上限和下限
多线程
程序、进程、线程
- 程序:一段静态代码
- 进程:正在运行的一个程序
-
线程的创建
继承Thread
public class MyThread extends Thread{@Overridepublic void run(){System.out.println("创建线程~启动线程调用run方法");}}
实现Runnable接口
public class Hello implements Runnable{@Overridepublic void run(){System.out.println("实现Runnable接口");}}
线程中常用方法
start():启动线程,执行run()
- run():执行的操作在run()方法中
- currentThread():静态方法,当前线程
- getName():获取线程名
- setName():设置线程名
- yield():释放CPU使用权
- join():线程a中调用线程b的join(),此时线程a就进入阻塞状态,直到线程b完全执行完以后,线程a才结束阻塞状态
- stop():已过时,强制结束线程
- sleep():休眠,进入阻塞,同步代码块中不会释放锁
- isAlive():线程是否存活
- getPriority():获取优先级 1~10,默认5
-
线程的同步
同步代码块(synchronized)
synchronized(对象/同步监视器){...}
同步方法(synchronized)
public synchronized void show(String name){...}
Lock(锁)
jdk5.0开始,显示锁
- java.util.concurrent.locks.Lock接口是控制多个线程进行共享资源的工具
- ReentrantLock类实现了Lock,可以加锁,释放锁
```java
class A{
private final ReentrantLock lock = new ReentrantLock();
public void m(){
}lock.lock();try{//保证线程安全的代码}catch(){...}finally{lock.unlock();}
}
<a name="E8E7v"></a>### 单例模式(饿汉式,线程安全)```javaclass Singleton{private Singleton(){}private static Singleton instance = null;public static Singleton getInstance(){if(instance == null){synchronized(Singleton.class){if(instance == null){instance = new Singleton();}}}return instance;}}
线程的通信
- wait():线程阻塞,释放锁,进入等待
- notify()/notifyAll():唤醒等待该对象监控权(锁)的一个/所有线程,有这个锁才能调用
使用两个线程交替打印1~100
//使用两个线程打印1~100,交替打印class Number implements Runnable{private int number = 1;private Object obj = new Object();@Overridepublic void run(){while(true){synchronized(obj){obj.notify();if(number <= 100){try{Thread.sleep(10);}catch(InterruptedException e){e.printStackTrace();}System.out.println(Thread.currentThread().getName() + ":" + number);number++;try{//使这个线程进入阻塞:释放锁obj.wait();}catch(InterruptedException e){e.printStackTrace();}}else{break;}}}}}
生产者消费者问题
//生产者消费者问题class Clerk{private int productCount = 0;//生产产品public synchronized void produceProduct(){if(productCount < 20){productCount++;System.out.println(Thread.currentThread().getName() + ":开始生产第" + productCount + "个产品");notify();}else{try{wait();}catch(InterruptedException e){e.printStackTrace();}}}//消费产品public synchronized void consumeProduct(){if(productCount > 0){System.out.println(Thread.currentThread().getName() + ":开始消费第" + productCount + "个产品");productCount--;notify();}else{try{wait();}catch(InterruptedException e){e.printStackTrace();}}}}//生产者class Producer extends Thread{private Clerk clerk;public Producer(Clerk clerk){this.clerk = clerk;}@Overridepublic void run(){System.out.println(getName() + ":开始生产产品.....");while(true){try{sleep(10);}catch(InterruptedException e){e.printStackTrace();}clerk.produceProduct();}}}//消费者class Consumer extends Thread{private Clerk clerk;public Consumer(Clerk clerk){this.clerk = clerk;}@Overridepublic void run(){System.out.println(getName() + ":开始消费产品.....");while(true){try {Thread.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}clerk.consumeProduct();}}}
JDK5.0新增创建线程方式
实现Callable接口
- 相比run()方法,可以有返回值
- 方法可以抛出异常
- 支持泛型的返回值
- 需要借助FutureTask类,比如获取返回结果
```java
//1.创建一个实现Callable的实现类
class NumThread implements Callable{
//2.实现call方法,将此线程需要执行的操作声明在call()中
@Override
public Object call() throws Exception {
} } public class ThreadNew { public static void main(String[] args) {int sum = 0;for (int i = 1; i <= 100; i++) {if(i % 2 == 0){System.out.println(i);sum += i;}}return sum;
}//3.创建Callable接口实现类的对象NumThread numThread = new NumThread();//4.将此Callable接口实现类的对象作为传递到FutureTask构造器中,创建FutureTask的对象FutureTask futureTask = new FutureTask(numThread);//5.将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()new Thread(futureTask).start();try {//6.获取Callable中call方法的返回值//get()返回值即为FutureTask构造器参数Callable实现类重写的call()的返回值。Object sum = futureTask.get();System.out.println("总和为:" + sum);} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}
}
<a name="m1rSJ"></a>#### 线程池<a name="jbAau"></a>## Java输入输出流<a name="jAfEd"></a>### 字节流<a name="NNAsu"></a>#### 字节输入流- InputStream接口(抽象基类)- FileInputStream文件输入流<a name="py48G"></a>#### 字节输出流- OutputStream接口(抽象基类)- FileOutputStream文件输出流<a name="snZqh"></a>#### 复制文件```javapublic void copyFile(String srcPath,String destPath){FileInputStream = null;FileOutputStream = null;try{File src = new File("srcPath");File dest = new File("destPath");fis = new FileInputStream(src);fos = new FileOutputStream(dest);byte[] buf = new byte[1024];int len;while((len = fis.read(buf)) != -1){fos.write(buf, 0, len);}}catch(IOException e){e.printStackTrace();}finally{if(fis != null){try{fis.close();}catch (IOException e) {e.printStackTrace();}}if(fos != null){try{fos.close();}catch (IOException e) {e.printStackTrace();}}}}
字符流
字符输入流
- Reader接口(抽象基类)
-
字符输出流
Writer接口(抽象基类)
-
缓冲流
提供流的读取、写入速度
提高读写速度的原因:内部提供了一个缓冲区 BufferInputStream
- BufferOutputStream
- BufferReader
BufferWriter
//实现文件复制的方法public void copyFileWithBuffered(String srcPath,String destPath){BufferedInputStream bis = null;BufferedOutputStream bos = null;try {//1.造文件File srcFile = new File(srcPath);File destFile = new File(destPath);//2.造流//2.1 造节点流FileInputStream fis = new FileInputStream((srcFile));FileOutputStream fos = new FileOutputStream(destFile);//2.2 造缓冲流bis = new BufferedInputStream(fis);bos = new BufferedOutputStream(fos);//3.复制的细节:读取、写入byte[] buffer = new byte[1024];int len;while((len = bis.read(buffer)) != -1){bos.write(buffer,0,len);}} catch (IOException e) {e.printStackTrace();} finally {//4.资源关闭//要求:先关闭外层的流,再关闭内层的流if(bos != null){try {bos.close();} catch (IOException e) {e.printStackTrace();}}if(bis != null){try {bis.close();} catch (IOException e) {e.printStackTrace();}}//说明:关闭外层流的同时,内层流也会自动的进行关闭。关于内层流的关闭,我们可以省略.// fos.close();// fis.close();}}
处理流之转换流
InputStreamReader:将InputStream转换为Reader
OutputStreamWriter:将Writer转换为OutputStream
对象序列化
实现Serializable接口 ```java /**
- 对象流的使用
- 1.ObjectInputStream 和 ObjectOutputStream
- 2.作用:用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。 *
- 3.要想一个java对象是可序列化的,需要满足相应的要求。见Person.java *
- 4.序列化机制:
- 对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种
- 二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。
- 当其它程序获取了这种二进制流,就可以恢复成原来的Java对象。
*
- @author shkstart
@create 2019 上午 10:27 */ public class ObjectInputOutputStreamTest {
/ 序列化过程:将内存中的java对象保存到磁盘中或通过网络传输出去 使用ObjectOutputStream实现 / @Test public void testObjectOutputStream(){
ObjectOutputStream oos = null;try {//1.oos = new ObjectOutputStream(new FileOutputStream("object.dat"));//2.oos.writeObject(new String("我爱北京天安门"));oos.flush();//刷新操作oos.writeObject(new Person("王铭",23));oos.flush();oos.writeObject(new Person("张学良",23,1001,new Account(5000)));oos.flush();} catch (IOException e) {e.printStackTrace();} finally {if(oos != null){//3.try {oos.close();} catch (IOException e) {e.printStackTrace();}}}
}
/ 反序列化:将磁盘文件中的对象还原为内存中的一个java对象 使用ObjectInputStream来实现 / @Test public void testObjectInputStream(){
ObjectInputStream ois = null;try {ois = new ObjectInputStream(new FileInputStream("object.dat"));Object obj = ois.readObject();String str = (String) obj;Person p = (Person) ois.readObject();Person p1 = (Person) ois.readObject();System.out.println(str);System.out.println(p);System.out.println(p1);} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} finally {if(ois != null){try {ois.close();} catch (IOException e) {e.printStackTrace();}}}
} }
```java/*** Person需要满足如下的要求,方可序列化* 1.需要实现接口:Serializable* 2.当前类提供一个全局常量:serialVersionUID* 3.除了当前Person类需要实现Serializable接口之外,还必须保证其内部所有属性* 也必须是可序列化的。(默认情况下,基本数据类型可序列化)*** 补充:ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量*** @author shkstart* @create 2019 上午 10:38*/public class Person implements Serializable{public static final long serialVersionUID = 475463534532L;private String name;private int age;private int id;private Account acct;public Person(String name, int age, int id) {this.name = name;this.age = age;this.id = id;}public Person(String name, int age, int id, Account acct) {this.name = name;this.age = age;this.id = id;this.acct = acct;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", id=" + id +", acct=" + acct +'}';}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public Person(String name, int age) {this.name = name;this.age = age;}public Person() {}}class Account implements Serializable{public static final long serialVersionUID = 4754534532L;private double balance;@Overridepublic String toString() {return "Account{" +"balance=" + balance +'}';}public double getBalance() {return balance;}public void setBalance(double balance) {this.balance = balance;}public Account(double balance) {this.balance = balance;}}
随机存储文件流(RandomAccessFile类)
- 可以当输入流也可以当输出流
- 构造器
- public RandomAccessFile(File file, String mode)
- public RandomAccessFile(String name, String mode)
- mode参数
- r:只读
- rw:读写
- rwd:读写,同步文件内容更新
- rws:读写,同步文件内容和元数据的更新
- 文件不存在,创建;文件存在(默认覆盖)
