【15】Head First Java 学习笔记

HeadFirst Java

本人有C语言基础,通过阅读Java廖雪峰网站,简单速成了java,但对其中一些入门概念有所疏漏,阅读本书以弥补。

第一章 Java入门
第二章 面向对象
第三章 变量
第四章 方法操作实例变量
第五章 程序实战
第六章 Java函数库
第七章 继承与多态
第八章 深入多态
第九章 构造器与垃圾收集器
第十章 数字与静态
第十一章 异常处理
第十二章 GUI(内部类)
第十三章 Swing
第十四章 保存对象
第十五章 网络与线程


前言

终于来到一个超大头章节,网络与线程,后端开发的重要章节!这是让我们的程序连接到互联网世界的第一步!这一章以实现一个实时聊天程序为例子,介绍相关的内容~
在这里插入图片描述

连接、传送、接受

客户端的工作需要这三件事
1.与服务器建立连接
2.传送信息到服务器
3.从服务器接受信息

这之中涉及计算机网络的底层原理,但java.net包帮我们解决了,但还是应该深入去研究计算机网络相关知识。

建立Socket连接

Socket(java.net.Socket):是代表两个机器之间网络连接的对象
创建Socket连接需要知道机器在哪里,用哪个端口收发数据

Socket chatSocket = new Socket("196.164.1.103",5000);

在这里插入图片描述

TCP端口

网页服务器(HTTP)的端口号是80
TCP端口:16位宽的帮助客户端识别服务器特定服务程序的标志

不同程序不可共享一个端口
在这里插入图片描述
在这里插入图片描述

BufferedReader从Socket上读取数据

使用串流,Java的大部分I/O不在乎链接串流的上游
在这里插入图片描述

用PrintWriter写数据到Socket

相比读取,没有用缓冲区,原文说是每次都写入一个String,PrintWriter更标准
在这里插入图片描述

编写简单的服务器

需要一对Socket,一个等待用户请求(当用户创建Socket)的ServerSocket,一个与用户通信的Socket

对于服务器来说,这里1,3步的Socket是指一对Socket;第2步属于客户端做的事情
在这里插入图片描述

public void go() {try {ServerSocket serverSock = new ServerSocket(4242);while () {Socket sock = serverSock.accept();//停下来直到接收客户端请求//服务器创建出与客户端Socket通信的Socket,进行数据传送/*具体服务代码*/}}catch ()
}

具体代码 P486-

编写聊天客户端程序
第一版:可发送

客户端建立Socket连接到服务器,PrintWriter流获取Socket输出流
第二版:可发送和可接收
从服务器获得信息——与服务器Socket连接,BufferReader获取输入流
何时从服务器获得?
1.间隔查询
2.用户送出信息时,顺便读取信息
3.信息送到服务器上时读取

这里选择第三种方法,程序如何写呢?照前文提到的accept(),需要有个循环等待服务器信息,但GUI启动之后,只有事件触发才会有程序运转,循环应该放在哪里?

显然,我们这里需要同时执行两件事的程序,一个负责用户与GUI的交互,一个用于持续读取服务器的数据。这意味着我们需要新的线程与执行空间。

但现实我们并没有多个处理器CPU,Java的新线程并不会让OS多开一个进程,只是感觉像。这是一种用户态的多线程。具体的细节得学习操作系统,这里不多讲解。

线程与Thread

线程独立,对应独立的执行空间
Thread是Java中线程的类
在这里插入图片描述

多个执行空间?

真正的多线程(多空间)是多处理器并行执行多件事情。
实际:Java只是在底层OS上的执行的进程(即非并行),Java的线程实现模拟的并行(不同模拟空间的来回快速切换)

轮到Java进程时,JVM执行什么?——目前栈空间的最上层
在这里插入图片描述

如何启动新线程

Runnable job = new MyRunnable();//新建工作,runnable是接口
Thread thread = new Thread(job);//给工人安排工作,传入runnable(的run方法)
thread.start();//启动,执行工作(新空间第一个方法)

Thread是工人,Runnable是他的工作
Thread对象不可复用,线程的run()方法执行后,线程死亡。Thread对象还在堆上,一般方法可调用。

Runnable接口只有一个方法void run();
回忆:Runnable,为什么要作为接口?——便于多态,一种合约,不同的任务有不同实现方式的run()方法
不使用Runnable,用Thread子类实现run方法?——可以,但不够面向对象。从目的角度,理解为有特殊的工人,只执行特殊的任务。

线程的状态

新建——》可执行——》执行中

新建Thread对象
thread.start
JVM调度机制决定何时进入执行中状态
在这里插入图片描述

一、可执行与执行中交替

二、暂时不可执行(阻塞)

某些特殊原因,调转机制将进程 变为不可执行
在这里插入图片描述

线程调度器

调度器决定线程何时被执行,何时等待被执行,何时去阻塞。但它的机制是模糊的,没有API可以控制调度,就算同一台机器,其结果都是不可预测的。

经典的错误:在单一机器测试多线程程序,且认为其他机器的调度器有相同行为

在这里插入图片描述
在这里插入图片描述

图2第三部分,新建线程是被搁置的,这里写错了。

使用sleep()

让程序更好预测,强制当前进程进入一定时间阻塞。

可让所有线程有机会运行
会抛出InterruptException异常,需要try/catch块
在这里插入图片描述

多线程以及并发性问题

两个线程存取同一对象的数据,即两个执行空间对堆上同一对象执行getter,setter。这会引发严重的问题(如数据损毁)

关于数据的损毁,原书中举了一个有趣的例子,一对夫妻有公共资产,取钱,约定会先查询余额。丈夫查询后进入了睡眠,妻子在丈夫睡眠途中查询取钱。丈夫醒来不再查询,认为余额充足而取钱。最后导致直接负债。。。
相关代码P507,分析后的结论是:妻子或丈夫应该学会在另一方取钱前不进行查询操作,而这需要的是一个锁
在这里插入图片描述

对象的锁与同步化

synchronized(同步化),对方法声明修饰,让其像原子一样

原子(atomic):古典说法,不可分割之意

每个对象都有锁,可假设配有虚拟钥匙随时待命。大部分时间对象都没有被锁上。
锁只在同步化的方法上起作用,线程只有取得对象的锁(的钥匙),才能进入同步化的方法

具体的过程:
线程 调用 同步化方法
线程尝试取得 对象的锁(的钥匙)
若取得,其他线程不可进入 该对象的 任何同步化方法
完成方法后,解锁并释放钥匙

说是对象的锁,但其实锁住的是存取对象实例变量的方法(不让线程并发冲突)

经典并发问题:丢失更新问题
多个线程对余额进行+1操作

public class test implements Runnable {int balance;public void run() {inc();}public void inc() {//这里进行同步化修饰即可解决问题int i = balance;balance = i+1;}
}

在这里插入图片描述
在这里插入图片描述

同步化的代价

JVM查询钥匙的性能损耗
强制线程排队
死锁

局部同步化:

public void go() {do();//this.do();synchronized(this) {//参数写入对象,表示需要取用该对象的锁,this即当前对象(执行该行为的实例)//else}
}
死锁

两个线程互相持有对方需要的钥匙
在这里插入图片描述

处理死锁
数据库的方法:超时释放 + 事务回滚复原
Java:无处理机制,自行合理设计,学习《Java Thread》

其他

静态的方法可否同步化呢?

可以的,对应静态变量的保护,类也有锁(与钥匙)。线程需要取得类的锁,才能进入同步化的静态方法。

线程优先级

对调度器有一定影响,但依旧并不能确保准确性

为什么不把getter与setter同步化?

可以,但我们为什么同步化?是为了查询余额与提款 这两个不可分割的动作进行原子化。仅仅对getter与setter同步化,依旧会出现负债问题。

Singleton模式(单例模式)

class Accum {private static Accum a = new Accum();//静态实例private Accum() {}//私有构造函数
}

小结

本章很长!耐心看下来,很有收获,该书总能从为什么触发,一步一步引导你的思考。

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

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

相关文章

windows 驱动开发-DMA技术(三)

在早期,是按照基于包或者基于流的方式来描述DMA的,不过这个描述可能不准确,故在Vista之后修改为使用数据包/使用公共缓冲区的系统DMA。 简单的解释一下基于包和基于流的说法的原因,数据包是指一个个基于一定大小的数据块&#xf…

IDA pro动态调试so层初级教程

一、开启服务 adb push D:\MyApp\IDA_Pro_7.7\dbgsrv\android_server64 /data/local/tmpadb shell cd /data/local/tmp chmod 777 android_server64 ./android_server64二、IDA附加进程 十万个注意:IDA打开的so文件路径不能有中文 手机打开要调试的app 附加成功

讯飞星火大模型赋能教育,引领教育实现数字化转型 | 最新快讯

(原标题:讯飞星火大模型赋能教育,引领教育实现数字化转型) 随着人工智能的发展,大模型正成为人们获取知识、学习知识的“超级助手”,是解放生产力、释放想象力的“好帮手”。随着大模型在多个领域大放异彩…

guidance - Microsoft 推出的编程范式

文章目录 一、关于 guidance安装 二、加载模型llama.cppTransformersVertex AIOpenAI 三、基本生成四、限制的生成选择(基本)正则表达正则表达式来限制生成正则表达式作为停止标准 上下文无关语法 五、状态控制生成1、不可变对象中的状态2、有状态的 gui…

Nodejs 第六十九章(杀毒)

杀毒 杀毒(Antivirus)是指一类计算机安全软件,旨在检测、阻止和清除计算机系统中的恶意软件,如病毒、蠕虫、木马、间谍软件和广告软件等。这些恶意软件可能会对计算机系统和用户数据造成损害,包括数据丢失、系统崩溃、…

基于ROS从零开始构建自主移动机器人:仿真和硬件

书籍:Build Autonomous Mobile Robot from Scratch using ROS:Simulation and Hardware 作者:Rajesh Subramanian 出版:Apress 书籍下载-《基于ROS从零开始构建自主移动机器人:仿真和硬件》您将开始理解自主机器人发…

(1)从头搞懂 Transformer模型(图解)

1、Transformer简介 GPT回答:(面试被问到可以这么介绍) Transformer是一种用于处理序列数据的深度学习模型架构,最初由Vaswani等人在2017年的论文《Attention is All You Need》中提出。它在处理序列到序列(seq2seq&…

2024年Q1葡萄酒行业线上电商(京东天猫淘宝)销售排行榜

五一聚餐不可缺少饮品——葡萄酒。鲸参谋监测的线上电商平台(某东)Q1季度葡萄酒行业销售数据已揭晓! 从鲸参谋的数据中,我们可以明显看到今年Q1季度在线上电商平台(某东)葡萄酒行业的销售情况呈现出积极的…

Java面试八股之int和Integer有什么区别

int和Integer有什么区别 基本类型与包装类: int:int是Java中的一个基本数据类型(primitive type),用于表示整数。它直接存储数值,没有独立的对象实例,不涉及内存管理。 Integer:I…

WebGL渲染引擎优化方向 -- 加载性能优化

作者:caven chen 前言 WebGL 是一种强大的图形渲染技术,可以在浏览器中快速渲染复杂的 3D 场景。但是,由于 WebGL 的高性能和高质量要求,如果不注意性能优化,它可能会消耗大量的 CPU 和 GPU 资源,导致应用…

使用 VLC Media Player 播放 RTSP 流媒体

VLC 是一款自由、开源的跨平台多媒体播放器及框架,可播放大多数多媒体文件,以及 DVD、音频 CD、VCD 及各类流媒体协议,也可以播放 RTSP 流媒体。 一、简介: VLC Media Player 是一款功能强大且开源的跨平台多媒体播放器。 支持…

LeetCode 102.对称二叉树

题目描述 给你一个二叉树的根节点 root , 检查它是否轴对称。 示例 1: 输入:root [1,2,2,3,4,4,3] 输出:true示例 2: 输入:root [1,2,2,null,3,null,3] 输出:false提示: 树中节点数…

【免费Java系列】大家好 ,给大家出一些今天学习内容的案例点赞收藏关注,持续更新作品 !

多态 Java中的多态是指同一个方法在不同的对象上有不同的行为: 案例一 以下有四个类 : 动物类与狗、猫类 Test测试类 // 动物类 class Animal {public void sound() {System.out.println("动物发出声音");} }// 狗类 class Dog extends Animal {Overridepublic void…

Go实现树莓派按键识别

环境 在Windows要注意交叉编译设置, 这个库目前没有使用C, 所以不需要配置GCC、G, 配置如下 GOOSlinux GOARCHarm 代码 package mainimport ("fmt""github.com/stianeikeland/go-rpio/v4""os""time" )var (…

C语言-整体内容简单的认识

目录 一、数据类型的介绍二、数据的变量和常量三、变量的作用域和生命周期四、字符串五、转义字符六、操作符六、常见的关键字6.1 关键字static 七、内存分配八、结构体九、指针 一、数据类型的介绍 sizeof是一个操作符,是计算机类型/变量所占内存空间的大小   sc…

实验三 .Java 语言继承和多态应用练习 (课内实验)

一、实验目的 本次实验的主要目的是通过查看程序的运行结果及实际编写程序,练习使用 Java 语言的继承特性。 二、实验要求 1. 认真阅读实验内容,完成实验内容所设的题目 2. 能够应用多种编辑环境编写 JAVA 语言源程序 3. 认真体会多态与继承的作用…

【项目构建】04:动态库与静态库制作

OVERVIEW 1.编译动态链接库(1)编译动态库(2)链接动态库(3)运行时使用动态库 2.编译静态链接库(1)编译静态库(2)链接静态库(3)运行时使…

【数据结构-之八大排序(下),冒泡排序,快速排序,挖坑法,归并排序】

🌈个人主页:努力学编程’ ⛅个人推荐:基于java提供的ArrayList实现的扑克牌游戏 |C贪吃蛇详解 ⚡学好数据结构,刷题刻不容缓:点击一起刷题 🌙心灵鸡汤:总有人要赢,为什么不能是我呢 …

信息管理与信息系统就业方向及前景分析

信息管理与信息系统(IMIS)专业的就业方向十分广泛,包含计算机方向、企业信息化管理、数据处理和数据分析等,随着大数据、云计算、人工智能、物联网等技术的兴起,对能够处理复杂信息系统的专业人才需求激增,信息管理与信息系统就业…

动态数据结构中的表扩张性:摊还分析、伪代码与C语言实现

动态数据结构中的表扩张性:摊还分析、伪代码与C语言实现 引言表扩张性的概念摊还分析在表扩张性中的应用伪代码示例:TABLE-INSERT操作C语言实现结论 引言 在处理数据结构时,尤其是表(或数组),我们经常面临…