—併發包— 大型企業開發才用,我Java學得差不多以後再來學,主要是有點難,沒學泛型與集合… 練手的ConcurrentHashMap: import java.util.HashMap;import java.util.Hashtable;import java.util.concurrent.C ...
—併發包—
大型企業開發才用,我Java學得差不多以後再來學,主要是有點難,沒學泛型與集合…
練手的ConcurrentHashMap:
import java.util.HashMap;
import java.util.Hashtable;
import java.util.concurrent.ConcurrentHashMap;
public class bingfa {
public static HashMap<String,String> maps=new HashMap<>();
// public static Map<String,String> 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<String> keys=map.keySet();//獲取全部鍵的集合,Set無序不重覆
for (String key: keys){
System.out.println(key);
}
Collection<Integer> 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<String,Integer>> 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)
Inet4Address ip = (Inet4Address) Inet4Address.getLocalHost();
System.out.println(ip.getHostName());
System.out.println(ip.getHostAddress());
獲取網站的ip地址:InetAddress ip2=InetAddress.getByName(“www.hepingan.top”);
System.out.println(ip2.getHostName());
System.out.println(ip2.getHostAddress());
測試連接:InetAddress ip3=InetAddress.getByName(“www.baidu.com”);
System.out.println(ip3.isReachable(5000));//ping
相當於ping xxx,在規定時間內連接,成功輸出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<String ,Integer> maps=new HashMap<>();
Map<String,Integer> maps2=new LinkedHashMap<>();
Map<String,Integer> 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<String> keys=maps.keySet();//獲取全部鍵的集合,Set無序不重覆
for (String key: keys){
Integer value=maps.get(key);//獲取對應鍵的值
System.out.println(key+"="+value);
}
Collection<Integer> 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<String,Integer>> entries=maps.entrySet();//鍵值對方式
System.out.println(entries);
for (Map.Entry<String, Integer> 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);
}
}
}