第15章:网络与线程(网络联机)
在 Java中,所有网络运作的低层细节都已经由 java.net 函数库处理。Java中,传送和接收网络上的数据,是在链接上使用不同链接串流的输入和输出。
什么是 Socket 连接?
Socket 是个代表两台机器之间网络连接的对象(java.net.Socket)。什么是连接?就是两台机器之间的一种关系,让两个软件相互认识对方,能够彼此发送和接收数据。在Java中,这是一种让运行在Java虚拟机上的程序能够找到方法去通过实际的硬件(比如网卡)在机器之间传送数据的机制。
如何创建一个 Socket 连接呢?
要创建 Socket,得知道两项关于服务器的信息:它在哪里(IP地址)?它使用的是哪个端口号?
Socket chat = new Socket("196.164.1.103", 3000);
什么是 TCP 端口号?
TCP 端口号,是一个 16位宽、用来识别服务器上特定程序的数字。端口号,代表了服务器上执行软件的逻辑识别。如果没有端口号,服务器就无法分辨客户端是要连接哪个应用程序的服务。每个应用程序可能都有独特的工作交谈方式,如果没有识别就发送的话会造成很大的麻烦,所以在同一台机器上不同的应用程序服务其端口号一定不同。
从 0 ~ 1023 的TCP 端口号是保留已知的特定服务使用,我们不应该使用这些端口号。当我们开发自己的应用程序服务时,可以从 1024 ~ 65535 之间选择一个数字作为端口号。
如何从 Socket 上读取数据?
用串流来通过 Socket 连接来沟通。使用 BufferedReader 从 Socket上读取数据。在Java中,大部分的输入与输出工作并不在乎链接串流的上游是什么,也就是说可以使用BufferedReader读取数据而不用管串流是来自文件还是Socket。
// 1 - 建立对服务器的 Socket 连接
Socket chat = new Socket("192.168.1.100", 3000);
// 2 - 建立连接到Socket上低层的输入串流
InputStreamReader stream = new InputStreamReader(chat.getInputStream());
// 3 - 建立Buffer来提升数据读取的效率
BufferedReader reader = new BufferedReader(stream);
// 4 - 读取数据
String msg = reader.readLine();
read.close();
如何向 Socket 中写入数据?
使用 PrintWriter 是最标准的做法。它的 print() / println() 方法,就跟 System.out 里的方法刚好一样。
// 1 - 对服务器建立 Socket 连接
Socket chat = new Socket("192.168.1.100", 3000);
// 2 - 建立连接到 Socket 的 PrintWriter
PrintWriter writer = new PrintWriter(chat.getOutputStream());
// 3 - 写入数据
writer.println("hello world");
writer.print("hello socket");
如何编写一个 Socket 服务器?
public class TestSocket {
public void go() {
try {
// 创建 服务端Socket,并监听 3000端口
ServerSocket serverSocket = new ServerSocket(3000);
// 服务器进入无穷循环,等待客户端的请求
while(true) {
// 等待连接
Socket sock = serverSocket.accept();
// 当有连接时,向 socket中写入数据
PrintWriter writer = new PrintWriter(sock.getOutputStream());
writer.println("hello world");
writer.close();
}
} catch (IOException e) {
System.out.println(e);
}
}
public static void main(String[] args) {
TestSocket ts = new TestSocket();
// 启动 socket 服务
ts.go();
}
}
什么是 Java 线程?
1.一个Java线程(thread),就是一个独立的执行空间(stack)。Java语言中内置了多线程功能,线程的任务就是运行程序代码。
2.java.lang.Thread类,表示Java中的线程,使用它可以创建线程实例。
3.每个Java应用程序都会启动一个主线程——把 main() 方法放进它自己执行空间的最开始处。Java虚拟机会负责主线程的启动。
怎么理解多线程的工作原理?
当有超过一个以上的执行空间时,看起来像是有好几件事情同时在发生。实际上,只有真正的多核处理器系统才能够同时做好几件事情。使用Java多线程可以让它看起来好像同时在做多个事情。也就是说,执行运作可以在执行空间中非常快速地来回切换,因此你会感觉到每项任务都在执行。线程要记录的一项事物是目前线程执行空间做到了哪里。Java虚拟机,会在多个线程之间来回切换,直到它们都执行完为止。
如何创建一个新的线程?
对一个线程而言,Thread线程就是一个工人,而Runnable就是这个工作的工作。Runnable带有会放在执行空间的第一项的方法:run() 。Thread对象不可以重复使用,一旦该线程的run()方法完成后,该线程就不能再重新启动了。
public class TestThread implements Runnable {
// 实现 Runnable 接口的 run 方法
public void run() {
System.out.println("执行");
}
public static void main(String[] args) {
// 创建线程的工作任务
Runnable threadObj = new TestThread();
// 创建线程,并把工作任务传递给线程
Thread myThread = new Thread(threadObj);
// 启动线程
myThread.start();
}
}
线程有哪三种状态?
线程实例一旦 start() 后,会有三种可能的状态:可执行状态、执行中状态、堵塞状态。在不发生堵塞的情况下,线程会在可执行状态和执行中状态之间来来回回地切换。
什么是线程调度器?
线程调度器会决定哪个线程从等待状态中被挑出来运行,以及何时把哪个线程送回等待被执行状态。它会决定某个线程要运行多久,当线程被踢出去时,调度器也会指定线程要回去等待下一个机会或者是暂时地堵塞。我们无法控制线程调度器,没有API可以调用调度器,调度器在不同的Java虚拟机上也不尽相同。
线程调度器会做所有的决定,谁跑谁停都由它说了算。它通常是公平的,但没有人能保证这件事儿,有时候某些线程会很受宠,有些线程会被冷落。多个线程任务,谁先执行完谁后执行完,并不能人为地确定。
线程休眠 Thread.sleep()
如果想要确定其它线程有机会执行的话,就把线程放进休眠状态。当线程醒来的时候,它会进入可以执行状态等待被调度器挑出来执行。使用 sleep() 能让程序变得更加可预测。
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
e.printStackTrace();
}
给线程取个非默认的名称
Thread thread = new Thread(runnableOjb);
// 自定义线程的名字
thread.setName("a name");
// 获取当前在执行线程的名字
String name = Thread.currentThread().getName();
标签:Head,Java,Socket,Thread,读书笔记,线程,new,15,执行
From: https://www.cnblogs.com/LvJinshuai/p/16887166.html