Skip to main content

多线程与网络编程

多线程

tip

运行的本质是在多个线程中反复切换,也就是在运行过程中,当有多线程在执行的时候,CPU会给这两个线程反复分配资源,左右横跳。

进程与线程

进程是指一个在运行的程序,线程是进程中正在执行的部分。一个java程序有一个主线程,一般在无任何操作的情况下只有这一个线程,可以使用多线程类创建多个线程。

实现过程

使用Thread类或者其子类实现创建线程,然后在对应位置调用start方法启动对应的线程。多线程执行的生命周期如下:

创建Thread类实例->调用start()方法->就绪状态->执行run方法(CPU分配资源)->run方法执行完成->线程死亡(stop或destoy方法销毁)

一般情况下有两种使用方法,使用实例:

  • 创建Thread子类
class ThreadDemo extends Thread {
private String name;
ThreadDemo(String name) { this.name = name; }

@Override
public void run() { /*what you want to do*/ }
public void start() { /* create new Thread with Thread class and start it */ }
}
  • 使用Runnable接口
class RunnableDemo implements Runnable {
private Thread t;
RunnableDemo(String name) { this.name = name;}
public void run() { /* todo: what you want to do */ }
public void start() { t = new Thread(this); t.start();}
}

public static void main() {
Thread t1 = new Thread(new Runnable() {
//todo: what you want to do.
})
t1.start();
RunnableDemo r = new RunnableDemo("Thread-2");
r.start();
}

线程同步

线程同步时指为了避免同一个变量访问时造成冲突而设置的

public synchronized void isSyncA() {...} 
public synchronized void isSyncB() {...}
public static synchronized void isSyncC() {...}

网络

TCP/UDP

  • TCP

TCP英文全称Transmission Control Protocol,传输控制协议,是一种面向连接的基于字节流的传输层通信协议。

  • UDP

UDP英文全称User Datagram Protocol,用户数据报协议,一个无连接的协议,提供了应用程序之间要发送数据的数据报。

Socket

Socket,又称套接字通信,在客户端和服务端两端都创建套接字,然后客户端向服务端发送连接请求,请求建立连接。通过Socket对象来建立连接,建立连接的同时,客户端和服务端能够彼此进行写入和读取。客户端使用Socket创建对象,服务端使用ServerSocket创建对象。

  • 服务器实例化ServerSocket对象表示服务器上的端口通信
  • 在服务器调用accept方法,该方法会一直等待连接,直到有客户端向服务器发起请求时才会继续往下执行语句,每次连接成功后,accept方法都会返回一个新的Socket对象引用,该对象就表示当前所连接的对象。
  • 客户端使用Socket类连接到指定IP和端口的服务器,如果连接成功则也会创建一个新的Socket对象与服务端进行通信。

ServerSocket类

//创建绑定到特定端口的服务器套接字。
public ServerSocket(int port) throws IOException
//利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号。
public ServerSocket(int port, int backlog) throws IOException
//使用指定的端口、侦听 backlog 和要绑定到的本地 IP 地址创建服务器。
public ServerSocket(int port, int backlog, InetAddress address) throws IOException


// 将 ServerSocket 绑定到特定地址(IP 地址和端口号)。
public void bind(SocketAddress host, int backlog)

Socket类

// 创建一个流套接字并将其连接到指定主机上的指定端口号。
public Socket(String host, int port) throws UnknownHostException, IOException.
// 创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
public Socket(InetAddress host, int port) throws IOException
// 创建一个套接字并将其连接到指定远程主机上的指定远程端口。
public Socket(String host, int port, InetAddress localAddress, int localPort) throws IOException.
// 创建一个套接字并将其连接到指定远程地址上的指定远程端口。
public Socket(InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException.

// 将此套接字连接到服务器,并指定一个超时值。
public void connect(SocketAddress host, int timeout) throws IOException
// 返回此套接字的输入流。(输入到客户端)
public InputStream getInputStream() throws IOException
// 返回此套接字的输出流。(输出到服务端)
public OutputStream getOutputStream() throws IOException
// 关闭此套接字。
public void close() throws IOException

实例

Client:

public class GreetingClient {
public static void main(String [] args) {
String serverName = args[0];
int port = Integer.parseInt(args[1]);
try {
System.out.println("连接到主机:" + serverName + " ,端口号:" + port);
Socket client = new Socket(serverName, port);
System.out.println("远程主机地址:" + client.getRemoteSocketAddress());
OutputStream outToServer = client.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);

out.writeUTF("Hello from " + client.getLocalSocketAddress()); //写入到服务端
InputStream inFromServer = client.getInputStream();
DataInputStream in = new DataInputStream(inFromServer);
System.out.println("服务器响应: " + in.readUTF()); //从服务器接收
client.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}

Server:

public class GreetingServer extends Thread {
private ServerSocket serverSocket;
public GreetingServer(int port) throws IOException {
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(10000);
}
public void run() {
while(true) {
try {
System.out.println("等待远程连接,端口号为:" + serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println("远程主机地址:" + server.getRemoteSocketAddress());
DataInputStream in = new DataInputStream(server.getInputStream());
System.out.println(in.readUTF()); // 从客户端接收
DataOutputStream out = new DataOutputStream(server.getOutputStream());
out.writeUTF("谢谢连接我:" + server.getLocalSocketAddress() + "\nGoodbye!"); //写入到客户端
server.close();
} catch(SocketTimeoutException s) {
System.out.println("Socket timed out!");
break;
} catch(IOException e) {
e.printStackTrace();
break;
}
}
}
public static void main(String [] args) {
int port = Integer.parseInt(args[0]);
try {
Thread t = new GreetingServer(port);
t.run();
} catch(IOException e) {
e.printStackTrace();
}
}
}