Java多多积累之线程池、网络编程、内部类完整讲解

线程安全问题

线程安全,必然会带来性能的降低,线程安全,适合多线程访问。
线程不安全,相对于线程安全性能较高,线程不安全,适合单线程访问。

线程池

1、池的本质,就是一种“缓存”技术,是否要缓存一个对象,取决于该对象的创建成本,但是使用缓存技术也要考虑系统内存大小;缓存的本质就是牺牲空间换取时间,线程对象的成本较大,所以在适当的时候选择使用线程池。
2、使用线程池的原因:多线程运行时间,系统不断的启动和关闭新线程,成本非常高,会过渡消耗系统资源,以及过渡切换线程的危险,从而导致系统资源的崩溃,这时,线程池就是最好的选择。
3、线程池的概念:线程池就是预先在内存中创建好一些线程,它们的集合称为线程池,使用线程池可以很好的提高性能,线程池在系统启动时即创建大量空闲的线程,程序将一个任务传给线程池,线程池就会启动一个线程来执行这个任务,执行结束以后,该线程并不会死亡,而是再次返回线程池中成为一个空闲状态,等待执行下一个任务。
4、线程池的工作机制:在线程池的编程模式下,任务是提交给整个线程池,而不是直接提交给某个线程,线程池在拿到任务后,就在内部寻找是否有空闲的线程,如果有,则将任务交给这个空闲的线程;一个线程同时只能执行一个任务,但是可以同时向一个线程池提交多个任务。

package com.wlx.day12;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolDemo
{public void  threadpool()throws Exception{//创建线程池对象ExecutorService threadpool = Executors.newCachedThreadPool();//使用线程池中的线程threadpool.execute(new Runnable() {@Overridepublic void run() {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"---");}});//使用线程完成以后,让其空闲1000毫秒Thread.sleep(1000);//再次使用线程池threadpool.execute(new Runnable() {@Overridepublic void run() {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"***");}});//使用shutdown()关闭线程池threadpool.shutdown();}public static void main(String[] args)throws Exception{new ThreadPoolDemo().threadpool();}}

ThreadLocal

ThreadLocal采用了“以空间换时间”的方式,每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个变量,这样就避免了多个线程对共享数据/共享资源的操作发生错误的问题。

package com.wlx.day12;/*** 使用多线程完成飞机购票,某订票系统还剩5张票,现有3个人去买票,* 在买票时,会出现系统延迟的情况,请使用程序实现3人购票的情况。*/
public class Ticket implements Runnable
{//定义一个变量用于缓存剩余的5张票private Integer p = 5;//创建ThreadLocal对象private static  final  ThreadLocal<Integer>  local = new ThreadLocal<>();@Overridepublic   void run(){for (int i = 0; i < 10; i++){buyTicket();}}/*** 获取ThreadLocal中的对象* @return*/public Integer getTicket(){if(local.get() == null){local.set(p);}return  local.get();}/*** 买票的方法*/private void buyTicket() {//获取ThreadLocal中的票数Integer count = getTicket();if(count > 0){try {System.out.println("系统延迟中...");Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"---买票"+(count--));local.set(count);}}public static void main(String[] args){Ticket  t = new Ticket();//创建3个线程代表3个人Thread  tom = new Thread(t,"tom");Thread  jim = new Thread(t,"jim");Thread  lilei = new Thread(t,"lilei");//3个人去买票tom.start();jim.start();lilei.start();}
}

volatile

volatile解决脏读(可见性),不会重排序,但是不能保证原子性,如果要保证原子性还是需要使用加锁,或使用ThreadLocal。

网络编程

端口号取值范围:0~65535,建议使用9999以上的端口号。

TCP编程

TCP编程,在发送和接收数据时,必须等待服务端启动后,才可以进行链接,然后才可以进行信息发送,发生数据时,不会出现丢失数据报包的情况。

服务端

package com.wlx.day12;import java.io.DataInputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;/*** 服务器端*/
public class Server
{public static void main(String[] args)throws Exception{//创建服务器端对象ServerSocket  serverSocket = new ServerSocket(10002);System.out.println("等待客户端链接...");while (true){//等待客户端链接Socket s =  serverSocket.accept();//创建字节输入流对象InputStream inputStream = s.getInputStream();//创建DataInputStream对象DataInputStream  dis = new DataInputStream(inputStream);System.out.println("IP:"+s.getInetAddress()+"\t 说:"+dis.readUTF());}}
}

客户端

package com.wlx.day12;import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;/*** 客户端*/
public class Client
{public static void main(String[] args)throws Exception{//创建客户端对象Socket  s = new Socket("192.168.219.1",10001);//创建字节输出流对象OutputStream  os =  s.getOutputStream();//创建DataOutputStream对象DataOutputStream dos = new DataOutputStream(os);//向服务端发送信息dos.writeUTF("hello server");}
}

图形化界面

package com.wlx.day12;import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.time.LocalDateTime;public class FrameServer
{public static void main(String[] args){//创建图形化界面的顶层窗口对象JFrame  jf = new JFrame("聊天窗口");//创建聊天窗口的文本域窗口对象JTextArea  jta = new JTextArea();//创建滚动条对象,并将jta添加进来JScrollPane  jsp = new JScrollPane(jta);//创建一个JPanel对象JPanel  jp = new JPanel();//创建文本框对象JTextField  jtf = new JTextField(20);//创建按钮对象JButton  jButton = new JButton("发送");jp.add(jtf);jp.add(jButton);//将jsp以及文本域添加到顶层窗口中,默认添加到中间位置jf.add(jsp);//添加到jf的最下面jf.add(jp,BorderLayout.SOUTH);//设置窗口大小jf.setSize(600,300);//设置显示位置jf.setLocation(300,300);//设置窗口可见jf.setVisible(true);//禁止最大化jf.setResizable(false);//设置窗口关闭按钮可以进行关闭jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);String ip = "192.168.219.1";int port = 10002;//添加文本框监听处理jtf.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {try {//创建客户端对象Socket  s = new Socket(ip,port);//创建字节输出流对象OutputStream os =  s.getOutputStream();//创建DataOutputStream对象DataOutputStream dos = new DataOutputStream(os);String msg = jtf.getText();jtf.setText("");//向服务端发送信息dos.writeUTF(msg);} catch (IOException ex) {ex.printStackTrace();}}});//为按钮添加监听jButton.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {try {//创建客户端对象Socket  s = new Socket(ip,port);//创建字节输出流对象OutputStream os =  s.getOutputStream();//创建DataOutputStream对象DataOutputStream dos = new DataOutputStream(os);String msg = jtf.getText();jtf.setText("");//向服务端发送信息dos.writeUTF(msg);} catch (IOException ex) {ex.printStackTrace();}}});try {//创建服务器端对象ServerSocket serverSocket = new ServerSocket(port);jta.append("服务器已启动,等待客户端链接...");jta.append("\n");while (true){//等待客户端链接Socket s =  serverSocket.accept();//创建字节输入流对象InputStream inputStream = s.getInputStream();//创建DataInputStream对象DataInputStream dis = new DataInputStream(inputStream);jta.append(LocalDateTime.now()+" :"+s.getInetAddress()+" 说:"+dis.readUTF()+"\n");jta.append("\n");}} catch (IOException e) {System.out.println("出现异常了...");}}
}

UDP编程

UDP编程,在发送和接收数据时,不用等待链接后再发送,可以直接发送,数据报包丢失对于UDP是正常现象。

卖家

发送数据。

package com.wlx.day12;import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;/*** UDP卖家*/
public class Seller
{public static void main(String[] args)throws Exception{DatagramSocket  ds = new DatagramSocket(10003);byte[]  b = "hello".getBytes();InetAddress ia = InetAddress.getLocalHost();System.out.println(ia);//10004是买家的端口号DatagramPacket  dp = new DatagramPacket(b,b.length,ia,10004);ds.send(dp);System.out.println("包裹已发出");}}

买家

接收数据

package com.wlx.day12;import java.net.DatagramPacket;
import java.net.DatagramSocket;/*** UDP买家*/
public class Buyer
{public static void main(String[] args)throws Exception{DatagramSocket  ds = new DatagramSocket(10004);byte[] b = new byte[1024];DatagramPacket dp = new DatagramPacket(b,b.length);ds.receive(dp);String s = new String(b);System.out.println("接收到的包裹是:"+s);}
}

内部类(了解)

定义:
定义在类的内部的类就是内部类,即定义在一个类的类体中或一个方法中的类就是内部类。
实例内部类
静态内部类
局部内部类
匿名内部类

1.1、实例内部类

定义:
没有被static静态修饰的,直接定义在类体中的一个类就是实例内部类。
实例内部类的实例对象是在所在类的实例基础上进行创建的。
实例内部类中的实例方法,调用外部类中的实例成员可以通过如果下格式调用:
外部类名.this.实例成员
实例内部类中也可以编写静态成员。
实例内部类中的静态成员使用和外部类类似,不能在静态成员中使用this关键字。

1.2、静态内部类

定义:
被static静态修饰的,直接定义在类体中的一个类就是静态内部类。
静态内部类中在使用外部类的成员时,和前面一样,只有一点,不能直接在静态内部类中使用外部类的this关键字。

1.3、匿名内部类

格式:
new 子类或实现类()
{
子类类体/实现类类体
};
备注:
子类用的是父类的类名。
实现类用的是接口的类名。
备注:
匿名内部类中,除了不能写构造方法,其他都可以写,但是还是要使用多态的方式访问匿名内部类中的方法,由于属性没有多态,匿名内部类中的属性只能在匿名内部类中使用。

package com.wlx.day12;/*** 外部类*/
public class ClassDemo
{String username = "jim";static int  uage = 678;String usersex = "man";static int userage = 89;/*** 定义一个实例内部类*/public  class  InnerClass{private static String username = "tom";private  int userage = 123;public InnerClass(){System.out.println("InnerClass---");}public static void  staticMethod(){ClassDemo cd = new ClassDemo();System.out.println("staticMethod---");System.out.println("uage---"+uage);System.out.println("usersex ---"+cd.usersex);System.out.println("cd.username ---"+cd.username);}public void  noStaticMethod(){System.out.println("no  Static  Method ");System.out.println("uage---"+uage);System.out.println("usersex ---"+usersex);System.out.println("ClassDemo.this.username ---"+ClassDemo.this.username);System.out.println("ClassDemo.userage---"+ClassDemo.userage);}}public  void  outMethod(){//创建内部类对象InnerClass  ic = new InnerClass();System.out.println(ic.userage);ic.noStaticMethod();//System.out.println(InnerClass.username);InnerClass.staticMethod();}public  static class StaticInnerClass{private static String username2 = "tom";private  int userage2 = 123;public StaticInnerClass(){System.out.println("InnerClass---");}public static void  staticMethod2(){ClassDemo cd = new ClassDemo();System.out.println("staticMethod---");System.out.println("uage---"+uage);System.out.println("usersex ---"+cd.usersex);System.out.println("cd.username ---"+cd.username);}public void  noStaticMethod2(String username2){ClassDemo cd = new ClassDemo();System.out.println("no  Static  Method ");System.out.println("uage---"+uage);System.out.println("usersex ---"+cd.usersex);System.out.println("cd.username ---"+cd.username);System.out.println("ClassDemo.userage---"+ClassDemo.userage);System.out.println(this.userage2);}}public  void  outMethod2(){StaticInnerClass sic = new StaticInnerClass();System.out.println(sic.userage2);sic.noStaticMethod2("");//System.out.println(InnerClass.username);StaticInnerClass.staticMethod2();}public  void  hello(int a){//定义局部变量,默认情况下,局部变量在被局部内部类使用时,被final修饰String  str = "jbbl";int abc = a;class HelloWorld{private static String username = "tom";private  int userage = 123;public HelloWorld(){System.out.println("InnerClass---");}public static void  staticMethod(){ClassDemo cd = new ClassDemo();System.out.println("staticMethod---");System.out.println("uage---"+uage);System.out.println("usersex ---"+cd.usersex);System.out.println("cd.username ---"+cd.username);}public void  noStaticMethod(){System.out.println("no  Static  Method ");System.out.println("uage---"+uage);System.out.println("usersex ---"+usersex);System.out.println("ClassDemo.this.username ---"+ClassDemo.this.username);System.out.println("ClassDemo.userage---"+ClassDemo.userage);System.out.println(str);System.out.println(abc);System.out.println(a);}}HelloWorld helloWorld = new HelloWorld();}public static void main(String[] args) {//创建实例内部类对象
//        InnerClass  innerClass = new ClassDemo().new InnerClass();//等价于ClassDemo  cd = new ClassDemo();//创建实例内部类对象InnerClass  innerClass = cd.new InnerClass();cd.outMethod();//创建匿名内部类InterfaceDemo id = new InterfaceDemo(){static int userage = 123;static String username = "tom";static{System.out.println("static----");}{System.out.println("8888");}public void abstractorMethod(){}public static  void hello(){}public  void  world(){}};System.out.println(InterfaceDemo.userage);}}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据传输安全--SSL VPN

目录 IPSEC在Client to LAN场景下比较吃力的表现 SSL VPV SSL VPN优势 SSL协议 SSL所在层次 SSL工作原理 SSL握手协议、SSL密码变化协议、SSL警告协议三个协议作用 工作过程 1、进行TCP三次握手、建立网络连接会话 2、客户端先发送Client HELLO包&#xff0c;下图是包…

springboot项目从jdk8升级为jdk17过程记录

背景&#xff1a;公司有升级项目jdk的规划&#xff0c;计划从jdk8升级到jdk11 开始 首先配置本地的java_home 参考文档&#xff1a;Mac环境下切换JDK版本及不同的maven-CSDN博客 将pom.xml中jdk1.8相关的版本全部改为jdk17&#xff0c;主要是maven编译插件之类的&#xff0c…

ubuntu22.04 安装 NVIDIA 驱动以及CUDA

目录 1、事前问题解决 2、安装 nvidia 驱动 3、卸载 nvidia 驱动方法 4、安装 CUDA 5、安装 Anaconda 6、安装 PyTorch 1、事前问题解决 在安装完ubuntu之后&#xff0c;如果进入ubuntu出现黑屏情况&#xff0c;一般就是nvidia驱动与linux自带的不兼容&#xff0c;可以通…

找工作准备刷题Day10 回溯算法 (卡尔41期训练营 7.24)

回溯算法今天这几个题目做过&#xff0c;晚上有面试&#xff0c;今天水一水。 第一题&#xff1a;Leetcode77. 组合 题目描述 解题思路 从题目示例来看&#xff0c;k个数是不能重合的&#xff0c;但是题目没有明确说明这一点。 使用回溯算法解决此问题&#xff0c;利用树形…

数据结构 —— B+树和B*树及MySQL底层引擎

数据结构 —— B树和B*树及MySQL底层引擎 B树B*树B树的应用B树在MySQL中的应用MyISAMInnoDB 我们之前学习了B树的基本原理&#xff0c;今天我们来看看B树的一些改良版本——B树和B*树。如果还没有了解过的小伙伴可以点击这里&#xff1a; https://blog.csdn.net/qq_67693066/ar…

【MySQL进阶之路 | 高级篇】MVCC三剑客:隐藏字段,Undo Log,ReadView

1. 再谈隔离级别 我们知道事务有四个隔离级别&#xff0c;可能存在三种并发问题&#xff1a; 在MySQL中&#xff0c;默认的隔离级别是可重复读&#xff0c;可以解决脏读和不可重复读的问题&#xff0c;如果仅从定义的角度来看&#xff0c;它并不能解决幻读问题。如果我们想要解…

Nacos-2.4.0最新版本docker镜像,本人亲自制作,部署十分方便,兼容postgresql最新版本17和16,奉献给大家了

基于Postgresql数据库存储的nacos最新版本2.4.0,采用docker镜像安装方式 因业务需要,为了让nacos支持postgresql,特意花了两天时间修改了源码,然后制作了docker镜像,如果你也在找支持postgresql的nacos最新版本,恭喜你,你来的正好~ nacos-2.4.0 postgresql的数据库脚本…

安宝特方案|解放双手,解决死角,AR带来质量监督新体验

AR质量监督 解放双手&#xff0c;解决死角 在当今制造业快速发展的背景下&#xff0c;质量监督成为确保产品高质量和完善的管理制度的关键环节。然而&#xff0c;传统的质量监督方式存在诸多挑战&#xff0c;如人工操作带来的效率低下、查岗不及时、摄像头死角等问题。 为了解…

本地部署,Whisper: 开源语音识别模型

目录 简介 特点 应用 使用方法 总结 GitHub - openai/whisper: Robust Speech Recognition via Large-Scale Weak SupervisionRobust Speech Recognition via Large-Scale Weak Supervision - openai/whisperhttps://github.com/openai/whisper 简介 Whisper 是一个由 O…

GoogleCTF2023 Writeup

GoogleCTF2023 Writeup Misc NPC Crypto LEAST COMMON GENOMINATOR? Web UNDER-CONSTRUCTION NPC A friend handed me this map and told me that it will lead me to the flag. It is confusing me and I don’t know how to read it, can you help me out? Attach…

软件更新的双刃剑:从”微软蓝屏”事件看网络安全的挑战与对策

引言 原文链接 近日&#xff0c;一场由微软视窗系统软件更新引发的全球性"微软蓝屏"事件震惊了整个科技界。这次事件源于美国电脑安全技术公司"众击"提供的一个带有"缺陷"的软件更新&#xff0c;如同一颗隐形炸弹在全球范围内引爆&#xff0c;…

17.5【C语言】static的补充说明

static &#xff08;静态的) 作用&#xff1a;修饰局部变量&#xff0c;修饰全局变量&#xff0c;修饰函数 对比两段代码 #include <stdio.h> void test() {int a 5;a;printf("%d ", a); } int main() {int i 0;for(i0; i<5; i){test();}return 0; } …

高并发内存池——链表设计

自由链表类的设计 由于申请的空间块经过对齐之后大小至少为8&#xff0c;因此可以考虑在未被使用的内存块中取前8字节存储下一个空间的地址 FreeList类初步声明 class FreeList { private:void* _freelistnullptr; //自由链表头指针size_t _size0; //自由链表的长度size_t …

【Django】anaconda环境变量配置及配置python虚拟环境

文章目录 配置环境变量配置python虚拟环境查看conda源并配置国内源在虚拟环境中安装django 配置环境变量 control sysdm.cpl,,3笔者anaconda安装目录为C:\ProgramData\anaconda3 那么需要加入path中的有如下三个 C:\ProgramData\anaconda3 C:\ProgramData\anaconda3\Scripts C:…

最新风车IM即时聊天源码及完整视频教程2024年7月版

堡塔面板 试验性Centos/Ubuntu/Debian安装命令 独立运行环境&#xff08;py3.7&#xff09; 可能存在少量兼容性问题 不断优化中 curl -sSO http://io.bt.sy/install/install_panel.sh && bash install_panel.sh 1.宝塔环境如下: Nginx 1.20 Tomcat 8 MySQL 8.0 R…

Java 开发环境配置

1. 下载 JDK 直接在oracle 官网下载 https://www.oracle.com/java/technologies/downloads或者使用博主已经从oracle下载的 jdk21&#xff1a;https://download.csdn.net/download/u011171506/89585231jdk8&#xff1a;https://download.csdn.net/download/u011171506/8958523…

快醒醒,别睡了!...讲《数据分析pandas库》了—/—<4>

一、废话不多说&#xff0c;直接开讲 1、DataFrame的索引和切片 1.1 选择列 当想要获取 df 中某列数据时&#xff0c;只需要在 df 后面的方括号中指明要选择的列即可。如果是 一列&#xff0c;则只需要传入一个列名;如果是同时选择多列&#xff0c;则传入多个列名即可&#xf…

SAPUI5基础知识20 - 对话框和碎片(Dialogs and Fragments)

1. 背景 在 SAPUI5 中&#xff0c;Fragments 是一种轻量级的 UI 组件&#xff0c;类似于视图&#xff08;Views&#xff09;&#xff0c;但它们没有自己的控制器&#xff08;Controller&#xff09;。Fragments 通常用于定义可以在多个视图中重用的 UI 片段&#xff0c;从而提…

集成千兆网口(Gigabit Ethernet Port)的作用主要是提供高速的有线网络连接,其工作原理涉及以下几个关键点:

传输速率&#xff1a; 千兆网口支持的最高传输速率达到1 Gbps&#xff08;即每秒10亿位&#xff09;&#xff0c;是传统百兆网口&#xff08;100 Mbps&#xff09;的十倍速度。这使得它能够处理更大量、更高质量的数据传输。 数据传输效率&#xff1a; 千兆网口能显著提高局域…

C#如何引用dll动态链接库文件的注释

1、dll动态库文件项目生成属性中要勾选“XML文档文件” 注意&#xff1a;XML文件的名字切勿修改。 2、添加引用时XML文件要与DLL文件在同一个目录下。 3、如果要是添加引用的时候XML不在相同目录下&#xff0c;之后又将XML文件复制到相同的目录下&#xff0c;需要删除引用&am…