对象序列化流
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class ObjectOutputStreamDemo01 {
public static void main(String[] args) throws IOException {
//ObjectOutputStream(OutputStream out):创建一个写入指定的OutputStream的ObjectOutputStream
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("Java基础语法\\oos.txt"));
//创建对象
Student s = new Student("Lucas",89,100,100);
oos.writeObject(s);
//释放资源
oos.close();
}
- 一定个对象想要被序列化,该对象所属的类必须要实现Serializable 接口
- 、serilizable是一个接口标记,实现该接口,不需要重写任何方法
对象反序列化流
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class ObjectInputStreamDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//ObjectInputStream(InputStream in):创建从指定的InputStream读取的ObjectStream
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("Java基础语法\\oos.txt"));
//Object readObject():读取对象
Object o =ois.readObject();
Student s =(Student)o;
System.out.println(s.getName()+","+s.getChinese());
//关闭资源
ois.close();
}
}
用对象序列化流序列化了一个对象后,假如我们修改了对象所属的文件,读取数据会不会出现问题?
会出现问题,抛出InvalidClassException异常
如果出了问题,我们该如何解决?
对对象所属类加一个serialVersionUID
private static final long serialVersionUID = 42L;
实现多线程
进程
进程:是正在运行的程序
是系统进行资源分配和调用的独立单位
每一个进程都有它自己的内存空间和系统资源
线程
线程:是进程中单个顺序控制流,是一条执行路径
public class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println(i);
}
}
}
public class MyThreadDemo {
public static void main(String[] args) {
MyThread m1 = new MyThread();
MyThread m2 = new MyThread();
//m1.run();
//m2.run();
//void start() 导致此线程开始执行:Java虚拟机调用此线程的run方法
m1.start();
m2.start();
}
}
设置和获取线程名称
public class MyThread extends Thread{
public MyThread (){}
public MyThread(String name){}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName()+":"+i);
}
}
}
public class MyThreadDemo {
public static void main(String[] args) {
//Thread(String name)
MyThread m1 = new MyThread("飞机");
MyThread m2 = new MyThread("大炮");
//m1.run();
//m2.run();
//void start() 导致此线程开始执行:Java虚拟机调用此线程的run方法
//setName(String name)
//m1.setName("飞机");
//m2.setName("大炮");
//static Thread currentThread() 返回对当前正在执行的线程对象的引用
System.out.println(Thread.currentThread().getName());
m1.start();
m2.start();
}
}
线程调度
Java使用的是抢占式调度模型
Thread类中设置和获取线程优先级的方法
public final int getPriority():返回此线程的优先级
public final void setPriority(int NewPriority):更改此线程的优先级
线程默认的优先级是5;线程的优先级默认范围是1-10;
线程控制
void join():等待这个线程死亡后,其他线程才可以开始
void setDaemon (boolean on):将此线程标记为守护线程,当运行的线程都是守护线程时,Java虚拟机退出
static void sleep (long millis):让当前正在执行的线程停留在指定的毫秒数
案例:卖票
public class SellTicket implements Runnable{
private int tickets=100;
@Override
public void run() {
/*
1.判断票数大于0,就卖票,并告知那个窗口卖的
2.卖了票之后,总票数减1;
3.票没了之后,也总有人来问,执行死循环
*/
while (true) {
if (tickets > 0) {
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
tickets--;
}
}
}
}
public class SellTicketDemo {
public static void main(String[] args) {
SellTicket st =new SellTicket();
Thread t1 = new Thread(st,"窗口1");
Thread t2 = new Thread(st,"窗口2");
Thread t3 = new Thread(st,"窗口3");
//启动线程
t1.start();
t2.start();
t3.start();
}
}
用同步代码块的方法解决多线程的数据安全问题
synchronized (任意对象) {
多条语句操作共享数据的代码
}
public class SellTicket implements Runnable{
private int tickets=100;
private Object obj=new Object();
@Override
public void run() {
/*
1.判断票数大于0,就卖票,并告知那个窗口卖的
2.卖了票之后,总票数减1;
3.票没了之后,也总有人来问,执行死循环
*/
while (true) {
synchronized (obj) {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
tickets--;
}
}
}
}
}
public class SellTicketDemo {
public static void main(String[] args) {
SellTicket st =new SellTicket();
Thread t1 = new Thread(st,"窗口1");
Thread t2 = new Thread(st,"窗口2");
Thread t3 = new Thread(st,"窗口3");
//启动线程
t1.start();
t2.start();
t3.start();
}
}
同步方法
同步方法:就是把synchronize关键字加到方法上
格式:
修饰符synchronized 返回值类型 方法名(方法参数){}
同步方法的锁对象是:this
接口组成更新
接口的组成:
-
常量
- public static final
-
抽象方法
- public abstract
-
默认方法
格式:public default 返回值类型 方法名(参数列表){}
范例:public default void show3(){}
默认方法不是抽象方法,所以不强制被重写。但重写的时候去掉default关键字
public 可以被省略,default不能被省略
-
静态方法
格式:public static 返回值类型 方法名(参数列表){}
范例:public static void show(){}
注意事项:
-
静态方法只能通过接口名调用,不能通过实现类名和对象名调用
-
public可以被省略,static 不能被省略
-
public interface Inter { void show(); default void method(){ System.out.println("Inter 中的默认方法执行了"); } public static void test(){ System.out.println("Inter 中的静态方法执行了"); } }
public class InterDemo { public static void main(String[] args) { Inter i =new InterImpl(); i.show(); i.method(); //静态方法只能别接口调用 Inter.test(); } }
-
-
私有方法
格式1:private 返回值类型 方法名 (参数列表){}
范例1:private void show()
格式2:private static 返回值类型 方法名(参数列表){}
范例2:private static void method()
注意事项 :
-
默认方法可以调用私有的静态方法和非静态方法
-
静态方法只能调用私有的静态方法
-