十四、TCP多线程、原子类AtomicInteger、日志、枚举

news2024/11/16 8:26:32

tcp多线程

tcp客户端 多线程收发代码

package com.heima.test2;

import java.io.*;
import java.net.Socket;
import java.nio.charset.Charset;
import java.util.Scanner;

class ClientSend implements Runnable {
    Socket socket;
    Scanner sc = new Scanner(System.in);

    public ClientSend(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        while (true) {
            try {
                System.out.println("输入发送的内容");
                String text = sc.next();

                //发送 创建字符缓冲流
                BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "gbk"));
                //写数据
                bw.write(text);
                //bw.newLine();如果接收方 按行接收 这里就需要添加newLine
                bw.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

class ClientReceive implements Runnable {
    Socket socket;

    public ClientReceive(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        while (true) {
            try {
                //接收
                BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "gbk"));
                //创建字符数组用来接收数据
                char[] cs = new char[1024];
                int len;
                //读取网络中的数据 存到字符数组中
                while ((len = br.read(cs)) != -1) {
                    System.out.println(new String(cs, 0, len));
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

public class Demo01 {
    public static void main(String[] args) {
        try {
            //创建发送端的socket对象 连接服务端的ip和端口
            Socket socket = new Socket("127.0.0.1", 15000);
            System.out.println("连接到服务器成功");
            //发送任务
            ClientSend clientSend = new ClientSend(socket);
            //接收的任务
            ClientReceive clientReceive = new ClientReceive(socket);

            //开启两个任务
            new Thread(clientSend).start();
            new Thread(clientReceive).start();

            //socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

tcp服务端 多线程收发代码

package com.heima.test2;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

class ServerSend implements Runnable {
    Socket accept;
    Scanner sc = new Scanner(System.in);

    public ServerSend(Socket accept) {
        this.accept = accept;
    }

    @Override
    public void run() {
        //发送 创建字符缓冲流
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream(), "gbk"));
        while (true) {
            try {
                System.out.println("输入发送的内容");
                String text = sc.next();
                //写数据
                bw.write(text);
                //bw.newLine();如果接收方 按行接收 这里就需要添加newLine
                bw.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

class ServerReceive implements Runnable {
    Socket accept;

    public ServerReceive(Socket socket) {
        this.accept = accept;
    }

    @Override
    public void run() {
        BufferedReader br = new BufferedReader(new InputStreamReader(accept.getInputStream(), "gbk"));
        while (true) {
            try {
                //接收
                //创建字符数组用来接收数据
                char[] cs = new char[1024];
                int len;
                //读取网络中的数据 存到字符数组中
                while ((len = br.read(cs)) != -1) {
                    System.out.println(new String(cs, 0, len));
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

public class Demo02 {
    public static void main(String[] args) {
        try {
            //创建服务端socket对象
            ServerSocket ss = new ServerSocket(15000);

            //接收客户端的请求
            Socket accept = ss.accept();
            System.out.println("收到来自" + accept.getRemoteSocketAddress() + "的连接");
            //发送任务
            ClientSend clientSend = new ClientSend(accept);
            //接收的任务
            ClientReceive clientReceive = new ClientReceive(accept);

            //开启两个任务
            new Thread(clientSend).start();
            new Thread(clientReceive).start();

            //socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

原子类AtomicInteger

  • 原子性

    • 所谓的原子性是指在一次操作或者多次操作中,要么所有的操作全部都得到了执行并且不会受到任何因素的干扰而中断,要么所有的操作都不执行,多个操作是一个不可以分割的整体。
  • public AtomicInteger(): 初始化一个默认值为0的原子型Integer

  • public AtomicInteger(int initialValue): 初始化一个指定值的原子型Integer

  • int get(): 获取值

  • int getAndIncrement(): 以原子方式将当前值加1,注意,这里返回的是自增前的值。 相当于i++

  • int incrementAndGet(): 以原子方式将当前值加1,注意,这里返回的是自增后的值。 相当于++i

  • int addAndGet(int data): 以原子方式将输入的数值与实例中的值(AtomicInteger里的value)相加,并返回结果。 +=

  • int getAndSet(int value): 以原子方式设置为newValue的值,并返回旧值。

乐观锁和悲观锁

乐观锁

日志

1概述

  • 概述

    程序中的日志可以用来记录程序在运行的时候点点滴滴。并可以进行永久存储。

  • 日志与输出语句的区别

    输出语句日志技术
    取消日志需要修改代码,灵活性比较差不需要修改代码,灵活性比较好
    输出位置只能是控制台可以将日志信息写入到文件或者数据库中
    多线程和业务代码处于一个线程中多线程方式记录日志,不影响业务代码的性能

2日志体系结构和logback

  • 体系结构

在这里插入图片描述

  • logback

    通过使用logback,我们可以控制日志信息输送的目的地是控制台、文件等位置。

    我们也可以控制每一条日志的输出格式。

    通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。

    最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

3入门案例【应用】

  • 使用步骤
    1. 导入logback的相关jar包

相关资料网盘地址:https://www.aliyundrive.com/s/wMiqbd4Zws6

在这里插入图片描述

在这里插入图片描述

  1. 编写logback配置文件

在这里插入图片描述

  1. 在代码中获取日志的对象

    • 注意导包 org.slf4j.xxx
  2. 按照级别设置记录日志信息

  • 代码示例
public class Demo01 {
    private static final Logger LOGGER = LoggerFactory.getLogger(Demo01.class);
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入您的姓名");
        String name = sc.next();
        LOGGER.debug("姓名是" + name);

        LOGGER.info("输了用户的姓名" + name);

        System.out.println("请输入您的年龄");
        String age = sc.next();
        LOGGER.info("输了用户的年龄" + age);
        try {
            LOGGER.warn("警告年龄必须是个数字,必须在正常范围内");
            int ageInt = Integer.parseInt(age);
            LOGGER.debug("姓名格式正确" + age);
        } catch (NumberFormatException e) {
            LOGGER.error("警告你不听 错了吧 " + age);
        }
    }
}
日志级别
  • 默认debug级别
// 测试类
public class Test01 {

    //获取日志的对象
    private static  final Logger LOGGER = LoggerFactory.getLogger(Test01.class);

    public static void main(String[] args) {
        //1.导入jar包
        //2.编写配置文件
        //3.在代码中获取日志的对象
        //4.按照日志级别设置日志信息
        LOGGER.debug("debug级别的日志");
        LOGGER.info("info级别的日志");
        LOGGER.warn("warn级别的日志");
        LOGGER.error("error级别的日志");
    }
}

枚举(掌握)

1概述

为了间接的表示一些固定的值,Java就给我们提供了枚举
是指将变量的值一一列出来,变量的值只限于列举出来的值的范围内

2定义格式

  • 格式
public enum s {   
	枚举项1,枚举项2,枚举项3;
}
注意: 定义枚举类要用关键字enum
  • 示例代码
// 定义一个枚举类,用来表示春,夏,秋,冬这四个固定值
public enum Season {
    SPRING,
    SUMMER,
    AUTUMN,
    WINTER;
} 

3枚举的特点【理解】

  • 特点

    • 所有枚举类都是Enum的子类

    • 我们可以通过"枚举类名.枚举项名称"去访问指定的枚举项

    • 每一个枚举项其实就是该枚举的一个对象

    • 枚举也是一个类,也可以去定义成员变量

    • 枚举类的第一行上必须是枚举项,最后一个枚举项后的分号是可以省略的,但是如果枚举类有其他的东西,这个分号就不能省略。建议不要省略

    • 枚举类可以有构造器,但必须是private的,它默认的也是private的。

      枚举项的用法比较特殊:枚举(“”);

    • 枚举类也可以有抽象方法,但是枚举项必须重写该方法

  • 示例代码

public enum Season {

    SPRING("春"){

        //如果枚举类中有抽象方法
        //那么在枚举项中必须要全部重写
        @Override
        public void show() {
            System.out.println(this.name);
        }

    },

    SUMMER("夏"){
        @Override
        public void show() {
            System.out.println(this.name);
        }
    },

    AUTUMN("秋"){
        @Override
        public void show() {
            System.out.println(this.name);
        }
    },

    WINTER("冬"){
        @Override
        public void show() {
            System.out.println(this.name);
        }
    };

    public String name;

    //空参构造
    //private Season(){}
  
    //有参构造
    private Season(String name){
        this.name = name;
    }
  
    //抽象方法
    public abstract void show();
}

public class EnumDemo {
    public static void main(String[] args) {
        /*
        1.所有枚举类都是Enum的子类
        2.我们可以通过"枚举类名.枚举项名称"去访问指定的枚举项
        3.每一个枚举项其实就是该枚举的一个对象
        4.枚举也是一个类,也可以去定义成员变量
        5.枚举类的第一行上必须是枚举项,最后一个枚举项后的分号是可以省略的,
          但是如果枚举类有其他的东西,这个分号就不能省略。建议不要省略
        6.枚举类可以有构造器,但必须是private的,它默认的也是private的。
          枚举项的用法比较特殊:枚举("");
        7.枚举类也可以有抽象方法,但是枚举项必须重写该方法
    */
  
        //第二个特点的演示
        //我们可以通过"枚举类名.枚举项名称"去访问指定的枚举项
        System.out.println(Season.SPRING);
        System.out.println(Season.SUMMER);
        System.out.println(Season.AUTUMN);
        System.out.println(Season.WINTER);
  
        //第三个特点的演示
        //每一个枚举项其实就是该枚举的一个对象
        Season spring = Season.SPRING;
        
        //调用成员变量
        System.out.println(Season.SPRING.name);
        System.out.println(Season.SUMMER.name);
        //调用重写的show方法
        Season.AUTUMN.show();
        Season.WINTER.show();
    }
}

4枚举的方法【应用】

  • 方法介绍

    方法名说明
    String name()获取枚举项的名称
    int ordinal()返回枚举项在枚举类中的索引值
    int compareTo(E o)比较两个枚举项,返回的是索引值的差值
    String toString()返回枚举常量的名称
    static T valueOf(Class type,String name)获取指定枚举类中的指定名称的枚举值
    values()获得所有的枚举项
  • 示例代码

public enum Season {
    SPRING,SUMMER,AUTUMN,WINTER;
}

public class EnumDemo {
    public static void main(String[] args) {
//        String name() 获取枚举项的名称
        String name = Season.SPRING.name();
        System.out.println(name);
        System.out.println("-----------------------------");

//        int ordinal() 返回枚举项在枚举类中的索引值
        int index1 = Season.SPRING.ordinal();
        int index2 = Season.SUMMER.ordinal();
        int index3 = Season.AUTUMN.ordinal();
        int index4 = Season.WINTER.ordinal();
        System.out.println(index1);
        System.out.println(index2);
        System.out.println(index3);
        System.out.println(index4);
        System.out.println("-----------------------------");

//        int compareTo(E o) 比较两个枚举项,返回的是索引值的差值
        int result = Season.SPRING.compareTo(Season.WINTER);
        System.out.println(result);//-3
        System.out.println("-----------------------------");

//        String toString()   返回枚举常量的名称
        String s = Season.SPRING.toString();
        System.out.println(s);
        System.out.println("-----------------------------");

//        static <T> T valueOf(Class<T> type,String name)
//        获取指定枚举类中的指定名称的枚举值
        Season spring = Enum.valueOf(Season.class, "SPRING");
        System.out.println(spring);
        System.out.println(Season.SPRING == spring);
        System.out.println("-----------------------------");

//        values()       获得所有的枚举项
        Season[] values = Season.values();
        for (Season value : values) {
            System.out.println(value);
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/136840.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2019年数维杯国际大学生数学建模B题无人机避障问题设计规划求解全过程文档及程序

2019年数维杯国际大学生数学建模 B题 无人机避障问题设计规划 问题重述&#xff1a; 任务1&#xff1a;假设无人机在飞行过程中不受风向、湿度等外界因素的影响&#xff0c;飞行速度和拍摄角度恒定&#xff0c;无人机对一定宽度的区域进行直线飞行模式航拍。执行此航拍的飞行…

SpringBoot(一): SpringBoot的创建和使用

Spring的创建和使用1. 什么是Spring&#xff1f;2. SpringBoot的优点3. SpringBoot项目的创建3.1 使用IDEA创建3.2 使用网页创建4. 项目目录介绍和运行4.1 目录介绍4.2 项目运行4.3 输出hello world4.4 约定大于配置1. 什么是Spring&#xff1f; Spring的诞生是为了简化Java程…

Spring-boot启动失败 Unregistering JMX-exposed beans on shutdown 异常处理

目录一、异常错误二、原因三、解决方法一、异常错误 Spring-boot启动Run时&#xff0c;出现 o.s.j.e.a.AnnotationMBeanExporter - Unregistering JMX-exposed beans on shutdown 错误 *************************** APPLICATION FAILED TO START Description: The Tomcat conn…

【小程序】包与数据共享

文章目录使用 npm 包Vant WeappAPI Promise化全局事件共享MobX分包分包概念使用分包独立分包分包预下载使用 npm 包 目前&#xff0c;小程序中已经支持使用 npm 安装第三方包&#xff0c;从而来提高小程序的开发效率。但是&#xff0c;在小程序中使用npm 包有如下 3 个限制&am…

【韩顺平Linux】学习笔记3

【韩顺平Linux】学习笔记3一、文件目录指令pwd指令 ls指令cd指令mkdir指令rmdir指令touch指令cp指令rm指令mv指令cat指令more指令less 指令echo指令 head指令tail指令> 指令 >>指令ln指令history指令二、时间日期指令三、查找指令四、压缩和解压一、文件目录指令 根目…

【前端】Vue项目:旅游App-(3)TabBar:点击active效果、点击路由跳转

文章目录目标代码与过程设置active主题颜色添加点击active效果点击路由跳转效果总代码修改或新增的文件common.cssindex.csstab-bar.vue目标 添加点击active效果实现点击路由跳转效果 上一篇TabBar搭建&#xff1a;【前端】Vue项目&#xff1a;旅游App-&#xff08;2&#xff…

LVGL学习笔记12 - 复选框CheckBox

目录 1. Parts 1.1 LV_PART_MAIN 1.2 LV_PART_INDICATOR 2. 状态 3. 样式 3.1 设置字符串颜色 3.2 设置点击框外框颜色 3.3 修改点击框弧度 3.4 修改字符串与点击框的间隔 4. 事件 复选框通过lv_checkbox_create创建。一个CheckBox由一个点击框加一个Label组成。 obj1 …

Minikube Mac 安装 使用

Minikube Mac 安装 使用 环境要求 硬件要求 至少 2核 CPUs2GB 以上内存20GB 以上磁盘空间网络环境容器或虚拟机, 例如: Docker, QEMU, Hyperkit, Hyper-V, KVM, Parallels, Podman, VirtualBox, or VMware Fusion/Workstation 本机环境 Mac Pro 10.13.6 Docker 18.09.1 …

半导体行业相关术语

目录 1.晶圆&#xff08;wafer&#xff09; 2. 自动化测试设备&#xff08;ATE Automatic Test Equipment&#xff09; 3.晶盒&#xff08;Cassette&#xff09; 4. 待测设备(DUT Device Under Test) 5. 探针接口板(PIB Prober Interface Board) 6. 设备接口板(DIB D…

干货 | web自动化总卡在文件上传和弹框处理上?

在有些场景中&#xff0c;需要上传文件&#xff0c;而 Selenium 无法定位到弹出的文件框&#xff0c;以及网页弹出的提醒。这些都是需要特殊的方式来处理。input 标签使用自动化上传&#xff0c;先定位到上传按钮&#xff0c;然后 send_keys 把路径作为值给传进去.如图所示&…

【计算机网络-物理层】通信基础

文章目录1 码元、速率、波特、带宽1.1 码元1.2 波特率1.3 比特率1.4 带宽1.5 相关例题2 奈氏准则、香农定理2.1 奈氏准则&#xff08;采样定理&#xff09;2.2 香农定理2.3 相关例题3 编码方式3.1 归零编码&#xff08;RZ&#xff09;3.2 非归零编码&#xff08;NRZ&#xff09…

【简单DP】[NOIP2007 普及组] 守望者的逃离

P1095 [NOIP2007 普及组] 守望者的逃离 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)题意&#xff1a;思路&#xff1a;独立做出来的一道DP&#xff01;一开始我去模拟过程找子问题&#xff0c;然后去找阶段是什么本来想的是以路程作为阶段&#xff0c;但是1e8数组开不下那么…

如何看待PyTorch 2.0?

作者&#xff5c;吴育昕 1 为什么是TorchDynamo Graph capture 把用户 Python 写的模型代码变成 graph&#xff0c;是一切编译的根基。而 PyTorch 在试了这么多方案之后似乎已经锁定 TorchDynamo 作为 graph capture 的未来方向了&#xff0c;所以写一点关于 TorchDynamo 的…

假如面试官问你Babel的原理该怎么回答

1. 什么是 Babel 简单地说&#xff0c;Babel 能够转译 ECMAScript 2015 的代码&#xff0c;使它在旧的浏览器或者环境中也能够运行。 // es2015 的 const 和 arrow function const add (a, b) > a b;// Babel 转译后 var add function add(a, b) {return a b; };Babel…

pwr | 谁说样本量计算是个老大难问题!?(二)(独立样本均值篇)

1写在前面 上次介绍了两组发生率的样本量计算方法&#xff0c;通过pwr包进行计算非常简单&#xff0c;可以有效地减少我们的工作量。&#x1f618; 有时候我们想比较两组之间的均值&#xff0c;如何计算样本量又一次成了老大难问题。&#x1f912; 本期我们还是基于pwr包&#…

【自学Java】Windows安装PyCharm IDE

Windows安装PyCharm IDE PyCharm下载 PyCharm下载地址 https://www.jetbrains.com/pycharm/PyCharm下载 打开上面的链接&#xff0c;打开 Python 的开发工具 PyCharm 的下载页面&#xff0c;如下图所示&#xff1a; 这里我们点击 Download&#xff0c;跳转到新的页面&#…

错过短视频,微博奔向新浪

以后新浪或许会被叫做“微博新浪”。 2022年12月23日晚&#xff0c;港股微博发布公告称&#xff0c;拟斥资15亿元收购新浪网技术有限公司100%股权。此举被外界解读为微博将反向收购新浪。 曾经&#xff0c;微博还是新浪移动互联网时代的“船票”。随着门户网站逐渐凋零&#…

基于ODX/OTX诊断的整车扫描

| ODX (Open Diagnostic data eXchange) 是基于XML语言、开放的诊断数据格式&#xff0c;用于车辆整个生命周期中诊断数据的交互。它一开始由ASAM提出并形成标准MCD-2D&#xff0c;后来以ODX2.2.0为基础形成了ISO标准——ISO 22901-1。 | OTX (Open Test sequence eXchange) …

Redis主从复制哨兵模式

Redis主从复制&哨兵模式一 什么是Redis主从复制1.1 主从复制的架构1.2 主从复制的原理1.3 主库是否要开启持久化1.4 辅助配置&#xff08;主从数据一致性配置&#xff09;二 主从复制配置2.1 slave 命令2.2 配置文件三 主从复制常见问题四 Redis哨兵机制4.1 什么是哨兵模式…

WebSocket服务端和客户端代码示例

目录一、WebSocket简介二、WebSocket服务端代码示例三、WebSocket客户端代码示例四、运行服务端和客户端&#xff0c;查看输出结果一、WebSocket简介 WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工&#xff08;full-duplex&#xff09;通信&#x…