P314-315 字节/符打印流
PrintStream ps = new PrintStream("test.txt");
//使用字节输出流的方法
ps.write(97);
// 使用特有方法写数据
ps.print(97); //write
ps.println("hello,world");
ps.close();
}
PrintWriter pw = new PrintWriter(new FileWriter("test"),true);
pw.write("hello");
pw.flush();
pw.println("hello");
pw.println("world");
pw.close();
P317-318 对象序列/反序列流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("test.txt"));
Student s1 = new Student("aaa",30);
oos.writeObject(s1); //把object给序列化到文件中
oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("test.txt"));
Object obj = ois.readObject();
Student s = (Student) obj;
System.out.println(s.getAge()+","+s.getName());
ois.close();
P319 serialVersionUID&transient
用对象系列化了一个对象后,如果我们修改了对象所属的类文件,对去数据会出现InvalidClassException的异常,所以,为了防止出问题,给这个对象所属的类加一个值:private static final long serialVersionUID = …,如果不期望某个属性参与序列化过程,则在这个属性的声明的时候,private transient int age,使用transient声明一下。
P320 Properties作为Map集合使用
Properties是一个Map体系的集合类,可以保存到流中或从流中加载。
Properties prop = new Properties();
prop.put("aaa","111");
prop.put("bbb","222");
prop.put("ccc","333");
Set<Object> keySet = prop.keySet();
for(Object key :keySet)
{
Object value = prop.get(key);
System.out.println(key+":"+value);
}
Properties作为集合的特有方法
Properties prop = new Properties();
prop.setProperty("aaa","111");
prop.setProperty("bbb","222");
prop.setProperty("ccc","333");
//根据键得到值
System.out.println(prop.getProperty("aaa"));
System.out.println(prop);
// 得到键
Set<String> names = prop.stringPropertyNames();
for(String key:names){
System.out.println(key);
String value = prop.getProperty(key);
System.out.println(key+","+value);
}
Properties和IO流相结合的方法
public static void main(String[] args) throws IOException {
// 把集合中的数据保存到文件
myStore();
//把文件中的数据加载到集合
myLoad();
}
private static void myLoad() throws IOException {
Properties prop = new Properties();
FileReader fr = new FileReader("test.txt");
prop.load(fr);
fr.close();
System.out.println(prop);
}
private static void myStore() throws IOException {
Properties prop = new Properties();
prop.setProperty("aaa","111");
prop.setProperty("bbb","222");
prop.setProperty("ccc","333");
FileWriter fw = new FileWriter("test.txt");
prop.store(fw,null); // null则不添加描述信息
fw.close();
}
P324 进程和线程
进程:是正在运行的程序
- 是系统进行资源分配和调用的独立单位。
- 每一个进程都有它自己的内存空间和系统资源。
线程:是进程中的单个顺序控制流,是一条执行路径
- 单线程:一个进程如果只有一条执行路径,则称为单线程程序。
- 多线程:一个进程如果有多条执行路径,则称为多线程程序。
P325 多线程的实现方式
在MyThread的类中:
Thread有默认名称,可以使用getName,即使子类没有name的成员,所以也可以在主函数中使用setName去重新命名线程的名字
public class MyThread extends Thread{
MyThread(){
}
MyThread(String name)
{
super(name);
}
@Override
public void run() {
for(int i=0;i<100;++i){
System.out.println (getName()+ ":" + i);
}
}
}
在主函数中:
MyThread my1 = new MyThread("my1");
MyThread my2 = new MyThread("my2");
my1.start();
my2.start();
System.out.println(Thread.currentThread().getName());
注意主函数中使用的是有参构造方法,其实是对Thread的name进行了赋值。
==System.out.println(Thread.currentThread().getName());==获得当前正在执行的线程的名称。
P327 线程调度(线程优先级)
//返回线程的优先级,也可以看出来线程的优先级默认是5,最大10,最小1
System.out.println(my1.getPriority());
System.out.println(my2.getPriority());
System.out.println(Thread.MAX_PRIORITY);
System.out.println(Thread.MIN_PRIORITY);
System.out.println(Thread.NORM_PRIORITY);
my1.setPriority(10);
my2.setPriority(5);
my3.setPriority(1);
P328 线程控制
sleep在重写run函数中使用:
@Override
public void run() {
for(int i=0;i<100;++i){
System.out.println (getName()+ ":" + i);
try{
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
join在主函数中使用:
my1.start();
try {
my1.join(); //阻塞,直到my1执行完,才开始my2 my3
} catch (InterruptedException e) {
e.printStackTrace();
}
my2.start();
my3.start();
设置守护线程
Thread.currentThread().setName("Main");
my1.setDaemon(true);
my2.setDaemon(true);
当主线程结束时,则my1,my2页结束。
P329 线程声明周期
弹幕说这是丁字裤图。。
P330 实现Runnable接口的方式实现多进程
注意实现Runnable的类就不能使用getName()的方法了,但是可以:
System.out.println(Thread.currentThread().getName() + ":" + i);
类中:
public class MyRunnable implements Runnable{
@Override
public void run() {
for(int i=0;i<100;++i){
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
主函数中:
MyRunnable my = new MyRunnable();
Thread t1 = new Thread(my);
Thread t2 = new Thread(my);
t1.start();
t2.start();
P333 同步代码块解决数据安全的问题
同步代码块通过使用以下的方式实现,任意对象可以看成是一把锁
好处:解决了多线程中的数据安全的问题
坏处:线程很多时,每个线程都会判断同步上的锁,这很耗费资源,无形中降低了程序的效率。
synchronized(任意对象){
}
@Override
public void run() {
while(true){
synchronized (obj){
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
tickets--;
}
}
}
}
P334 同步方法解决数据安全问题
此时方法的锁是this的锁,也就是相当于synchronized(this){}
public synchronized 返回值 方法名(){
}
335 线程安全的类
当使用多线程时,应该使用下面的类
查看他们的源码有没有被synchronized修饰
StringBuffer sb = new StringBuffer();
StringBuffer sb2 = new StringBuffer();
Vector<String> v = new Vector<String>();
ArrayList<String> array = new ArrayList<String>();
Hashtable<String,String> ht = new Hashtable<String,String>();
HashMap<String,String> hm = new HashMap<String,String>();
List<String> list = Collections.synchronizedList(new ArrayList<String>());
P336 Lock锁
private Lock lock = new ReentrantLock();
@Override
public void run() {
while(true){
try {
lock.lock();
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
tickets--;
}
}finally {
lock.unlock();
}
}
}
P337生产者与消费者
当方法内部使用wait()方法时,注意给方法加上synchronized关键字
P339 网络编程模块
计算机网络:指将地理位置不同的具有独立功能的多态计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理协调下,实现资源共享和信息传递的计算机系统。
网络编程:指再网络通信协议下,实现网络互联的不同计算机上运行的程序间可以进行数据交换。
网络编程三要素
IP地址
InterAddress的使用
可以通过主机名或者IP地址来获得,这里IP地址我随便弄了个,应该是自己电脑的。
InetAddress address = InetAddress.getByName("Phalange");
//InetAddress address = InetAddress.getByName("88.22.88.88");
String name = address.getHostName();
String ip = address.getHostAddress();
System.out.println("主机名:" + name);
System.out.println("IP address " + ip);
端口
协议
UDP通信原理
UDP发送数据
DatagramSocket ds = new DatagramSocket();
byte[] bys="hello,upd,i am coming..".getBytes(StandardCharsets.UTF_8);
//int length = bys.length;
//InetAddress address = InetAddress.getByName("Phalange");
//int port = 10086;
//DatagramPacket dp = new DatagramPacket(bys,length,address,port);
DatagramPacket dp = new DatagramPacket(bys, bys.length, InetAddress.getByName("Phalange"), 10086);
ds.send(dp);
ds.close();
保证发送的数据和接收的数据是一个端口的。
UDP接收数据
DatagramSocket ds = new DatagramSocket(10086);
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys, bys.length);
ds.receive(dp);
//解析数据包
byte[] datas = dp.getData();
int len = dp.getLength();
String dataString = new String(datas,0,len);
System.out.println(dataString);
ds.close();
TCP通讯原理
TCP发送数据
Socket s = new Socket(InetAddress.getByName("Phalange"),10000);
//Socket s = new Socket("192.162.1.1",10000);
OutputStream os = s.getOutputStream();
os.write("hello,tcp,iam coming".getBytes(StandardCharsets.UTF_8));
s.close();
TCP接收数据
ServerSocket ss = new ServerSocket(10000);
Socket s = ss.accept();
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys);
String data = new String(bys,0,len);
System.out.println("data is :"+data);
s.close();
ss.close();
TCP练习
Socket.shotdownOutput(); // 发送一个结束的标记
P355 lambda表达式
概述
小例子
new Thread(() -> {
System.out.println("多线程启动了");
}).start();
lambda表达式的标准格式
练习:抽象方法是三种实现
useEatable(new EatableImpl());
useEatable(new Eatable(){
@Override
public void eat() {
System.out.println("i am eat...");
}
});
// lambda
useEatable(()->{
System.out.println("i am eat....");
});
有返回值的重写
public static void main(String[] args) {
useAddalbe((int x,int y)->{
return x+y;
});
}
public static void useAddalbe(Addable a){
int sum = a.add(10,10);
System.out.println(sum);
}
lambda省略规则
// 参数的类型可以省略
useAddalbe((x,y)->{
return x+y;
});
// 如果只有一个参数,可以省略小括号;如果只有一行代码,可以省略大括号和分号,
//return 也可以省略
useFlyable(s-> System.out.println(s));
useAddalbe((x,y)->x+y);
lambda表达式的注意事项
一定要注意是接口!!并且有且仅有一个抽象方法!!
lambda表达式和匿名内部类别
P363 接口组成更新
接口中默认方法
接口中的静态方法
接口中的私有方法
P367 方法引用
体验小例子
usePrintable(s-> System.out.println(s));
//方法引用符号::
//可推到的就是课省略的
usePrintable(System.out::println);
== 方法引用符==
::为方法引用符,而他所在的表达式被称为方法引用。
引用类方法
引用类方法,其实就是引用类的静态方法
== 引用对象的实例方法==
使用PrintString这个类已经实现的方法来实现接口
PrintString ps = new PrintString();
usePrinter(ps::printUpper);
Lambda表达式被对象的实例方法替代的时候,他的形式参数全部传递给该方法作为参数。
引用类的实例方法
useMyString(String::substring);
Lambda表达式被类的实例方法替代的时候,他的第一个参数作为调动着,其他的参数全部传递给该方法作为参数。
引用构造器
useStudentBuilder((name,age)->{
return new Student(name,age);
});
useStudentBuilder(Student::new);
Lambda表达式被构造器代替的时候,他的全部参数被传给构造器作为参数。
函数式接口
函数式接口:有且仅有一个抽象方法的接口。
被@FunctionalInterface注解一下最好。
@FunctionalInterface
public interface FuncInterface {
void show();
}
函数式接口作为方法参数
函数式接口作为方法的返回值
P376 常用的函数式接口
Supplier接口
public static void main(String[] args) {
String s = getString(()->{
return "hello,java";
});
Integer i = getInteger(()->30);
System.out.println(i);
System.out.println(s);
}
private static Integer getInteger(Supplier<Integer> sup){
return sup.get();
}
private static String getString(Supplier<String> sup){
return sup.get();
}
Consumer接口
andThen方法
public static void main(String[] args) {
operatorString("abbcccc",(String s)-> System.out.println(s));
operatorString("abcdefg",(String s)->{
System.out.println(new StringBuilder(s).reverse().toString());
});
operatorString("aaa",s-> System.out.println(s),s->System.out.println(new StringBuilder(s).reverse().toString()));
}
private static void operatorString(String name, Consumer<String> com1,Consumer<String> com2){
// com1.accept(name);
// com2.accept(name);
com1.andThen(com2).accept(name);
}
private static void operatorString(String name, Consumer<String> com){
com.accept(name);
}
Predicate接口
.negate方法对test方法的结果做了一个逻辑非的操作。
public static void main(String[] args) {
//boolean b = checkString("hello",(String s)->s.length()>8);
//System.out.println(b);
//boolean b2 = checkString("hello,world",s -> s.length()>8);
//System.out.println(b2);
boolean b3 = checkString("hello",s->s.length()>8,s->s.length()<15);
System.out.println(b3);
}
private static boolean checkString(String s, Predicate<String> pre1,Predicate<String> pre2){
//boolean b1 = pre1.test(s);
//boolean b2 = pre2.test(s);
//boolean b3 = b1 && b2;
//return b3;
//return pre1.and(pre2).test(s);
return pre1.or(pre2).test(s);
}
private static boolean checkString(String s, Predicate<String> pre){
return pre.negate().test(s);
}
Function接口
public static void main(String[] args) {
convert("100",s->Integer.parseInt(s));
convert("100",Integer::parseInt);
convert(100,i->String.valueOf(i+400));
convert("100",Integer::parseInt,i->String.valueOf(i+100));
}
private static void convert(String s, Function<String,Integer> fun){
int i = fun.apply(s);
System.out.println(i);
}
private static void convert(int i,Function<Integer,String > fun){
String s = fun.apply(i);
System.out.println(s);
}
private static void convert(String s,Function<String,Integer> fun1,Function<Integer,String> fun2){
//Integer i = fun1.apply(s);
//String ss = fun2.apply(i);
String ss = fun1.andThen(fun2).apply(s);
System.out.println(ss);
}