—并发包—
大型企业开发才用,我Java学得差不多以后再来学,主要是有点难,没学泛型与集合…
练手的ConcurrentHashMap:
import java.util.HashMap;
import java.util.Hashtable;
import java.util.concurrent.ConcurrentHashMap;public class bingfa {
public static HashMapmaps=new HashMap();
// public static Map maps=new Hashtable();public static void main(String[] args) {
Runnable r1=new MyRunnable();
Thread t1=new Thread(r1,"线程1");
Thread t2=new Thread(r1,"线程2");t1.start();
t2.start();
try {
t1.join();//让t1跑完,主线程不能竞争t1的CPU
t2.join();//让t2跑完,主线程不能竞争t2的CPU
} catch (InterruptedException e) {
throw new RuntimeException(e);
}System.out.println("元素个数:"+maps.size());
}
static class MyRunnable implements Runnable{
@Override
public void run() {
for(int i=1;i<=500000;i++){
bingfa.maps.put(Thread.currentThread().getName()+i,Thread.currentThread().getName()+i);
}
}}
}
—Map集合—
Map集合特点:无序性,不重复性(后面重复的键对应的元素会覆盖前面的整个元素),无索引的,对值无要求都可以为null。一个元素的组成为键和值,一个键对应一个值,就像地图上一个地方对应一个地点名字,所以叫Map集合。
HashMap:无序,不重复,无索引,值不做要求。经典的用得最多。
LinkedHashMap:有序,不重复,无索引,值不做要求。
TreeMap:浮点型的大小比较按照自己的排序,不重复,无索引,值不做要求。
Map的创建:Map map=new HashMap/LinkedHashMap/TreeMap();ps:引用数据类型可以是其他类名的哦~
添加数据:map.put(xx,xx);
删除特定元素:map.remove(键);删除全部元素就直接map.clear();
判断是否包含某个键:map.containsKey(键);
判断是否包含某个值:map.containsValue(值);
将maps2的所有元素全部仍到maps中:map.putAll(maps2);
获取对应键的值:map.get(键);
Set keys=map.keySet();//获取全部键的集合,Set无序不重复
for (String key: keys){
System.out.println(key);
}
Collection values=map.values();//因为值可能有重复,所以用Collection集合
for (Integer value: values){
System.out.println(value+”,”+map.size());
}
遍历方法:
遍历方式1:键找值(key的值为String,value的类型为Integer):for(String key:maps.keySet()){Integer value =maps.get(key);System.out.println(key+”=”+value)};
遍历方式2:键值对方式获取:相较于键找值更加面向对象,但代码复杂,它是把键值对当成一个整体遍历,也就是直接使用foreac遍历:for(被遍历集合的元素类型 变量 :集合名称){…};有点像python的字典,创建方法:Set<Map.Entry> xxx=maps.entrySet();
遍历方式3(最简单的):k,v只是个随便定义的变量,名字乱取都行
maps.forEach((k,v) ->{
System.out.println(k+”–>”+v);
});
—-网络通信—-
C/S结构的软件开发:客户需要下载客户端,一更新客户端也要更新。
B/S结构软件开发:类似于网上开发,客服不用下客服端。
网络通信三要素:协议,IP地址,端口号。
协议就是计算机网络客户端与服务端通信必须事先约定和彼此遵守的通信规则,一般有HTTP,FTP,TCP,UDP,SSH,SMTP.
IP地址:Internet Protocol Address互联网协议地址。有IPv4和IPv6.
IPv4:4个字节,32位组成
端口:如果说IP相当于一个酒店,端口就相当于酒店的房间号。端口取值范围:0~65535.比如浏览器的端口号就是80。
查看自己的ip:在cmd命令板输入ipconfig,尝试连接:ping ip地址或网站域名。
获取本地地址对象:(如果是公网IP就会优先输出公网IP,没有就是本地IP)
Inet4Addressip=(Inet4Address)Inet4Address.getLocalHost();
System.out.println(ip.getHostName());
System.out.println(ip.getHostAddress());
获取网站的ip地址:InetAddressip2=InetAddress.getByName(“www.hepingan.top”);
System.out.println(ip2.getHostName());
System.out.println(ip2.getHostAddress());
测试连接:InetAddressip3=InetAddress.getByName(“www.baidu.com”);
System.out.println(ip3.isReachable(5000));//ping
相当于pingxxx,在规定时间内连接,成功输出true,失败false
UDP通信:
与服务端传输信息不需要进行交手,所以不怎么安全,但可以用作开发实时通讯等。
创建集装箱的参数:DatagramPacket packet =new DatagramPacket(数据包,数据包的长度,【IP地址】,【端口号】);发送的客户端要写【】内的,接受的服务端不用写。
创建接收和发送数据的码头:DataSocket socket =new DataSocket();
(客户端)发送数据:socket.send(packet);
(服务端)接收数据:socket.receive(packet);
关闭码头:socket.close();
TCP通信(重点):
一般web网站都是用的TCP/IP协议。
TCP/IP协议 ==> Transfer Control Protocol ==> 传输控制协议
TCP/IP协议的特点
* 面向连接的协议
* 只能由客户端主动发送数据给服务器端,服务器端接收到数据之后,可以给客户端响应数据。
* 通过三次握手建立连接,连接成功形成数据传输通道。
* 通过四次挥手断开连接
* 基于IO流进行数据传输
* 传输数据大小没有限制
* 因为面向连接的协议,速度慢,但是是可靠的协议。
客户端的开发流程:
1.客户端要请求于服务端的socket管道连接。
2.从socket通信管道中得到一个字节输出流
3.通过字节输出流给服务端写出数据。
服务端的开发流程:
1.注册端口。
2.接收客户端的Socket管道连接。
3.从socket通信管道中得到一个字节输入流。
4.从字节输入流中读取客户端发来的数据。
小结:
1.客户端用Socket连接服务端。Socket socket=new Socket(ip,port)
2.服务端用ServerSocket注册端口,接收客户端的Socket连接。ServerSocket ss=new ServerSocket(port);
3.通信是很严格的,对方怎么发,你就应该怎么收,对方发多少你就只能收多少。
4.实现的面向连接的socket端到端的通信管道,一方如果出现对象,另一方会出现异常!
2023最新IO传输方法:使用DataI/OStream数据输入输出流进行传输,对DataStream对象使用writeUTF和readUTF进行就收发送和读写。就不用用byte了
总的方法就是客户端先创建Socket管道用于数据的传输管道,需要输入传输的IP地址和端口,再创建OutputStream对象从Socket管道中得到一个字节输出流,然后用DataOutputStream包装成高级的数据输出流,最后用writeUTF(msg)就可以发送消息了。服务端先注册一个端口号:ServerSocket ss=new ServerSocket(端口号),然后等待连接管道Socket socket =ss.accept(),再创建InputStream并使用DataInputStream打包成数据输入流,最后创建个String类型变量使用readUTF()读写数据就行了。
volatile类型变量用于解决多个线程访问共享变量是会出现一个线程修改变量值后其他线程看不到最新的线程值。
TCP通信实现多个客服端和服务端发消息(未使用线程池的):学完网络通信能写出下面的就可以毕业了~
客户端:
package new_TCPstudy;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class Client {
public static void main(String[] args) throws IOException {
System.out.println("客服端启动");
Socket socket=new Socket(InetAddress.getLocalHost(),9999);
//从socket管道中得到一个字节输出流
OutputStream OutputStream=socket.getOutputStream();
//包装成高级的数据输出流
DataOutputStream dataOutputStream=new DataOutputStream(OutputStream);
Scanner scanner=new Scanner(System.in);
while (true){
System.out.println("请说:");
String msg=scanner.nextLine();
//输入exit退出客户端
if("exit".equals(msg)){
System.out.println("退出客服端...");
dataOutputStream.close();
socket.close();
break;
}
dataOutputStream.writeUTF(msg);
dataOutputStream.flush();
}
}
}
服务端:
package new_TCPstudy;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
System.out.println("服务端,启动!");
//为服务端注册端口
ServerSocket ss=new ServerSocket(9999);
//创建管道等待接收连接
while (true){
Socket socket=ss.accept();
System.out.println(socket.getInputStream()+"上线了~");
new ServerThread(socket).start();
}
}
public static class ServerThread extends Thread{
private Socket socket;
public ServerThread(Socket socket){
this.socket=socket;
}
@Override
public void run() {
try {
InputStream inputStream=socket.getInputStream();
//包装成高级的数据输入流
DataInputStream dataInputStream=new DataInputStream(inputStream);
while (true){
String msg=dataInputStream.readUTF();
System.out.println("收到来自"+socket.getRemoteSocketAddress()+"的消息:"+msg);
}
}catch (Exception e){
System.out.println(socket.getRemoteSocketAddress()+"下线了");
}
}
}
}
Map集合学习时的代码:
import java.sql.Connection;
import java.util.*;
public class MapDemo {
public static void main(String[] args) {
Map maps=new HashMap();
Map maps2=new LinkedHashMap();
Map maps3=new TreeMap();
System.out.println(maps2.isEmpty());//判断是否为空集合,是则返回true,反之
maps.put("food",5);
maps.clear();//清空
maps2.put("long",15);
maps.put("doll",1);
maps.put("Huawei",2);
maps.put("doll",10);//后面的把前面的覆盖了
maps.put("iphone",2);
maps.put(null,null);
maps.put("people",8);
maps.putAll(maps2);//将maps2的所有元素全部仍到maps中
maps.remove("people");//删除特定元素
Integer value1 =maps.get(null);//获取null的值
System.out.println(maps);
System.out.println(maps.get("iphone")+","+value1);//输出iphone的值和 null的值
Set keys=maps.keySet();//获取全部键的集合,Set无序不重复
for (String key: keys){
Integer value=maps.get(key);//获取对应键的值
System.out.println(key+"="+value);
}
Collection values=maps.values();//因为值可能有重复,所以用Collection集合
for (Integer value: values){
for(String key:maps.keySet()){
if(value==maps.get(key)){
System.out.println(value+"值的有"+key);
}
}
}
System.out.println(maps.size());// maps的大小
Set<Map.Entry> entries=maps.entrySet();//键值对方式
System.out.println(entries);
for (Map.Entry entry : entries) {
String key=entry.getKey();
Integer value=entry.getValue();
System.out.println(key+"-->"+value);
}
//最简单的遍历方法
maps.forEach((k,v) ->{
System.out.println(k+"-->"+v);
});
}
}
啤酒问题(递归思路):
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
/**
* 啤酒问题:Beer: 2/bottle,4 hats can change a beer,2 empty bottle can change a beer,question:how many bottle can 10 rmb drink?
*/
public class bbb {
public static int totalNumber;
public static int lastBottles;
public static int lastHats;
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("你带了多少钱:");
buy(sc.nextInt());
System.out.println("你能喝"+totalNumber+"瓶");
System.out.println("剩余瓶子数:"+lastBottles);
System.out.println("剩余盖子数:"+lastHats);
}
public static void buy(int money){
totalNumber+=money/2;
lastBottles+=money/2;
lastHats+=money/2;
int newNumber=0;
if(lastBottles>=2){
newNumber+=lastBottles/2;
lastBottles=lastBottles%2;
}
if(lastHats>=4){
newNumber+=lastHats/4;
lastHats=lastHats%4;
}
if (newNumber>0){
buy(newNumber*2);
}
}
}