网络 sort serversort URL 设计模式 枚举

现在是2018 11 28 17.56分,我望了望天空,感觉到几丝空虚,回到电脑前 就知道该写博客了

首先我们学习一个新的概念 网络
(本次博客依旧是根据我自己理解进行解释,可能有些内容遗漏)
在正式学习网络之前我们先要知道一些关于网络的协议
TCP/IP协议
tcp 传输控制协议
ip 网络地址协议
这样说可能有些抽象
TCP是将数据打包 并且规定其格式的一个规则
IP则是我门上网时的地址,
在我们进行游览网址等操作时,我们都需要遵守TCP/IP地址
举个例子
我们在打开链接游览网页时,我们就会向服务器端口发送一个请求,这个请求会根据TCP打包成一个包发送到服务器端 上面有这我们的IP地址,服务器再根据我们的IP地址进行反馈,当然这是简化的说法
具体的话 需要经过网络的四个层次

应用层常见协议
http 超文本传输协议(访问网页)
telnet 远程登录
ssh 远程登录(保证安全)
传输层协议
打包和确定目的应用程序
TCP(保障数据的可靠有序), UDP 不保证
http 占用80 端口
telnet 22
ssh 22
mysql 3306
互联网层
ip协议
网络访问层

上述内容现在只需理解,以后我们还会涉及到。

接下来我们在理解一下,常用的浏览器
这个我简单提及一下
一 IE
这个兼容性太差,不推荐使用
(不是故意黑IE)
二 火狐浏览器
这个浏览器比较好,推荐使用
三 谷歌游览器
这个游览器也比较好,推荐使用

接下来是一个重点
socket类 和 URL类
都在Java.net包下
使用也很简单 直接new 对象 调用其方法
这两个类我直接合对比一下。
在这里插入图片描述
这两个类使用起来都很简单方便
但是我们需要注意的是sort与URl的区别
sort一般用于本地链接的传输 更多的适用于局域网中,双方确定好端口以及地址进行数据传输
而URL更适用于 http网页上的数据内容传输

每个程序只能有一个端口
建议使用4位数以上的端口,因为有些windows程序会默认低位数端口
当我们端口重复使用时则会报错
以上为我们创建客户端

接下来我们使用一下服务器端口
使用的类也很简单
serversock
接下来我模拟一下 客户端和服务器的关系
这是我的服务器

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(5000);
        Socket socket = serverSocket.accept();
        InputStream in = socket.getInputStream();
        OutputStream out = socket.getOutputStream();
        int len =0;
        byte[] bytes = new byte[1024];
        while ((len=in.read(bytes))!=-1){
            out.write(bytes,0,len);
        }
        String s = new String(bytes);
        System.out.println("服务器收到"+s);
    }
}

这是我的客户端

package Study01;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class Client {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("localhost",5000);
        OutputStream out = socket.getOutputStream();
        out.write("你好\n".getBytes());
        out.write("无极之道,在我内心延续\n".getBytes());
        InputStream in = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len=0;
        while ((len=in.read(bytes))!=-1){
            break;
        }
        String s = new String(bytes);
        System.out.println("客户端收到\n"+s);

    }
}

localhost 的意思是本地ip 不用去查找自己的ip
用的是5000端口
在这里插入图片描述

这是运行结果
在我们学习网络的过程中
我们也需要注意到网络中使用了IO流
所以我们可以在该程序代码上进行改进
引入多线程 和 scanner 进行手动操作 和多线程高效处理

在这里我们需要注意的一点是
socket使用的是阻塞IO,而阻塞io的特点,一个socket执行io读写操作会阻塞其它io的读写
一个线程内io的读写是串行的,可以用多线程的方法来解决, 建议使用线程池而不是自己手动创建线程

这就意味着我们在 以后写网络的程序中我们需要更多的用到 多线程的处理

并发量再高怎么办
非阻塞IO NIO, nonBlocking IO, new IO
线程(多路)复用
一个线程可以同时处理多个io操作, 减少了线程的数量,能够应付更高的并发
WEB服务器 tomcat 雄猫(BIO,NIO)
Netty 服务器, 封装了NIO技术,并发能力很高
spark 分布式计算框架
Redis 缓存服务器 (C) 单线程 QPS 10万

非阻塞IO现阶段只限了解

下来我们学一下枚举类
关键字enum
该类适用于
当对象的个数已经固定,并有限时,例如:性别,星期等等
枚举类中也可以有方法,构造方法,属性
但构造方法不能是公共的
枚举类不能继承
在这里插入图片描述
接下来 我们学习一下设计模式
我着重讲几个例子

第一个 当我们的属性过多 而 有些属性不需要设定时 ,我们怎么做
构造器!

public class Student {
    private int age;
    private String Sex;
    private String name;

    private Student(int age, String sex, String name) {
        this.age = age;
        Sex = sex;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", Sex='" + Sex + '\'' +
                ", name='" + name + '\'' +
                '}';
    }

    public static class bulid{
        private int age;
        private String Sex;
        private String name;
        public bulid setage(int age){
            this.age=age;
            return this;
        }
        public bulid setSex(String Sex){
            this.Sex=Sex;
            return this;
        }
        public bulid setname(String name){
            this.name=name;
            return this;
        }
        public Student bulider(){
            return new Student(this.age,this.Sex,this.name);
        }
    }

    public int getAge() {
        return age;
    }

    public String getSex() {
        return Sex;
    }

    public String getName() {
        return name;
    }
}

该方法原理为在 对象内部创建内部类 内部类与其属性内容一致 在内部类中创建返回值为自身的方法
最后构造一个builder方法 返回对象类型
此时对象的所有属性都有了默认值
非常方便的 模式 建议使用

当我们只想创建一个对象时我们怎么做
方法1 :饿汉式

public class pattern01 {
    private pattern01(){
        
    }
    public static pattern01 me=new pattern01();
    public pattern01 show(){
        return me;
    }
}

通过静态加载 使其对象只能new一次
且返回的都是同一对象

方法2 :懒汉

public class pattern02 {
    private pattern02(){

    }
    private static pattern02 me;
    public synchronized pattern02 getinstance(){
        if(me==null){
            me= new pattern02();
        }
        return null;
    }
}

该方法在通过上锁 (再多线程中避免创建多个对象)的形式 来进行创建对象 比较耗费资源

方法3 :枚举

方法4 :懒汉优化

public class pattern03 {
    private pattern03(){

    }
    static class pattern003{
        static pattern03 me =new pattern03();
    }
    public static pattern03 getinstance(){
        return pattern003.me;
    }

}

该方法为最优方法 采用静态内部类只加载一次的特性 ,再利用静态方法 将其对象创建出来 为最优方法
推荐 面试时使用
提及一下
破坏单例的办法:

  1. 反射可以调用私有构造
  2. 反序列化可以破坏单例 (可以阻止)

迭代器模式以及 比较器 在之前学过了 在双链 集合 和 集合排序中用的比较多 这里就不提及了
最后一个是克隆

克隆分为深度克隆和浅度克隆

public class pattern06 implements Cloneable{
    private int age;
    private String name;
    private int weight;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    @Override
    public String toString() {
        return "pattern06{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", weight=" + weight +
                '}';
    }

    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

}

以上为浅度克隆
利用的是cloneable接口
然而这个方法的缺点是 拷贝了其地址 没有拷贝其内容

深度克隆为

public class pattern066 implements Cloneable,Serializable {
    private int age;
    private String name;
    private int weight;

    public Object clone(){
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            new ObjectOutputStream(out).writeObject(this);
            byte[] bytes = out.toByteArray();
            ByteArrayInputStream in = new ByteArrayInputStream(bytes);
            ObjectInputStream inputStream = new ObjectInputStream(in);
            return inputStream.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    @Override
    public String toString() {
        return "pattern066{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", weight=" + weight +
                '}';
    }
}

利用序列化以及反序列化将其再次创建 完完全全是新的内容

以上为本次博客的内容
PS,通过上次测验 我严重的感受到了自己的不足,对之前学习内容遗忘没有办法让我去做复杂程度更高的代码
包括最近的一次爬虫代码,正则代码那部分我已经忘光了,这次爬虫代码说实话没有做出来,思路我有,但是代码写不出来,语法上的漏洞还有对之前学习的东西没办法灵活运用,哇,这么想想好麻烦…,我只能在接下来更努力一些了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值