Java 网络编程和多线程

在这里插入图片描述

欢迎来到Cefler的博客😁
🕌博客主页:折纸花满衣
🏠个人专栏:Java

在这里插入图片描述


👉🏻实现客户端和服务端交互

Java 的网络编程是通过 Java 提供的标准库来实现的,主要依赖于 java.net 包。以下是一些基础概念和常用类的介绍:

1. 基本概念

  • 客户端-服务器模型:在网络编程中,通常采用客户端-服务器架构,其中客户端向服务器发送请求,服务器处理请求并返回响应。
  • Socket:Socket 是实现网络通信的基本单元,能够在不同主机上进行数据交换。

2. 常用类

  • Socket:用于客户端与服务器之间的连接。
  • ServerSocket:用于服务器端监听客户端请求。
  • InetAddress:用于表示 IP 地址。
  • URL:用于处理统一资源定位符,提供访问网络资源的功能。
  • URLConnection:用于与 URL 进行交互。

3. 简单示例

客户端代码
import java.io.*;
import java.net.*;

public class Client {
    public static void main(String[] args) {
        try (Socket socket = new Socket("localhost", 12345)) {
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            
            out.println("Hello, Server!");
            String response = in.readLine();
            System.out.println("Server response: " + response);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
服务器代码

import java.io.*;
import java.net.*;

public class Server {
    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(8888)) {
            System.out.println("Server is listening on port 8888");
            while (true) {
                Socket socket = serverSocket.accept();
                new Thread(new ClientHandler(socket)).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class ClientHandler implements Runnable {
    private Socket socket;

    public ClientHandler(Socket socket) {
        this.socket = socket;
    }

    public void run() {
        try  {
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String message = in.readLine();
            System.out.println("Received: " + message);
            out.println("Echo: " + message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

4. 注意事项

  • 多线程:服务器通常需要处理多个客户端连接,因此使用多线程是一个常见的做法。
  • 异常处理:网络编程中,异常处理非常重要,以确保程序的稳定性。
  • 资源管理:确保在使用完 Socket 和 I/O 流后关闭它们,以避免资源泄漏。

👉🏻实现客户端聊天窗口

SimpleChatServer

package MyPackage2;

import java.io.*;
import java.net.*;
import java.util.*;
public class SimpleChatServer {

    ArrayList<PrintWriter> clientOutputStreams;

    public static void main(String[] args) {
        new SimpleChatServer().go();
    }
    public void go() {
        //请手动输入代码
        clientOutputStreams = new ArrayList<>();
        try {
            ServerSocket serverSocket = new ServerSocket(5000);
            while(true)
            {
                Socket clientSocket = serverSocket.accept();
                PrintWriter writer = new PrintWriter(clientSocket.getOutputStream());
                clientOutputStreams.add(writer);
                //创建一个线程,用于接收客户消息
                Thread t = new Thread(new ClientHandler(clientSocket));
                t.start();
                System.out.println("got a connection");
            }

        }catch(Exception ex){
            ex.printStackTrace();
        }
    }
    public class ClientHandler implements Runnable {
        BufferedReader reader;
        Socket socket;
        public ClientHandler(Socket clientSocket) {
            //请手动输入代码
            try {
                socket = clientSocket;
                InputStreamReader isReader = new InputStreamReader(clientSocket.getInputStream());
                reader = new BufferedReader(isReader);
            }catch (Exception ex){
                ex.printStackTrace();
            }
        }
        public void run() {
            String message;
            try {
                while ((message = reader.readLine()) != null) {
                    String printMessage = socket.getPort() + "端口:"+message;
                    System.out.println("read: " + printMessage);
                    tellEveryone(printMessage);
                }
            } catch (Exception ex) {
                //ex.printStackTrace();
            }
        }
    }
    public void tellEveryone(String message) {
        //请手动输入代码
        Iterator<PrintWriter> it = clientOutputStreams.iterator();
        while(it.hasNext()){
            try {
                PrintWriter writer = it.next();
                writer.println(message);
                writer.flush();//刷新缓冲区
            }catch (Exception ex){
                ex.printStackTrace();
            }
        }
    }
}

SimpleChatClient

package MyPackage2;

import java.io.*;
import java.net.*;
import java.util.*;
public class SimpleChatServer {

    ArrayList<PrintWriter> clientOutputStreams;

    public static void main(String[] args) {
        new SimpleChatServer().go();
    }
    public void go() {
        //请手动输入代码
        clientOutputStreams = new ArrayList<>();
        try {
            ServerSocket serverSocket = new ServerSocket(5000);
            while(true)
            {
                Socket clientSocket = serverSocket.accept();
                PrintWriter writer = new PrintWriter(clientSocket.getOutputStream());
                clientOutputStreams.add(writer);
                //创建一个线程,用于接收客户消息
                Thread t = new Thread(new ClientHandler(clientSocket));
                t.start();
                System.out.println("got a connection");
            }

        }catch(Exception ex){
            ex.printStackTrace();
        }
    }
    public class ClientHandler implements Runnable {
        BufferedReader reader;
        Socket socket;
        public ClientHandler(Socket clientSocket) {
            //请手动输入代码
            try {
                socket = clientSocket;
                InputStreamReader isReader = new InputStreamReader(clientSocket.getInputStream());
                reader = new BufferedReader(isReader);
            }catch (Exception ex){
                ex.printStackTrace();
            }
        }
        public void run() {
            String message;
            try {
                while ((message = reader.readLine()) != null) {
                    String printMessage = socket.getPort() + "端口:"+message;
                    System.out.println("read: " + printMessage);
                    tellEveryone(printMessage);
                }
            } catch (Exception ex) {
                //ex.printStackTrace();
            }
        }
    }
    public void tellEveryone(String message) {
        //请手动输入代码
        Iterator<PrintWriter> it = clientOutputStreams.iterator();
        while(it.hasNext()){
            try {
                PrintWriter writer = it.next();
                writer.println(message);
                writer.flush();//刷新缓冲区
            }catch (Exception ex){
                ex.printStackTrace();
            }
        }
    }
}

在这里插入图片描述

👉🏻 Java Swing

JTextArea

JTextArea 是 Java Swing 中用于显示和编辑多行文本的组件。它是一个非常灵活的文本区域,可以用于各种图形用户界面(GUI)应用程序。以下是 JTextArea 的一些主要特点和用法:

主要特点

  1. 多行文本:可以显示和编辑多行文本,适合用于输入较长的内容,如文章、评论等。

  2. 可滚动:通常与 JScrollPane 一起使用,以便在文本较多时提供滚动功能。

  3. 文本格式化:支持基本的文本格式化,比如设置字体、大小、颜色等。

  4. 换行和自动换行

    • 可以设置为自动换行,确保长文本在可见区域内换行。
    • 也可以禁用换行,使文本在一行中显示。
  5. 事件处理:可以添加监听器来处理用户的输入事件,比如键盘输入、焦点变化等。

常用方法

  • 构造函数

    JTextArea textArea = new JTextArea(rows, columns);
    

    可以指定文本区域的行数和列数。

  • 设置文本

    textArea.setText("初始文本");
    
  • 获取文本

    String text = textArea.getText();
    
  • 追加文本

    textArea.append("要追加的文本");
    
  • 清空文本

    textArea.setText("");
    
  • 设置可编辑性

    textArea.setEditable(false); // 设为不可编辑
    
  • 设置换行

    textArea.setLineWrap(true); // 启用自动换行
    textArea.setWrapStyleWord(true); // 仅在单词边界处换行
    

示例代码

下面是一个简单的示例,展示如何创建一个包含 JTextArea 的 GUI 应用:

import javax.swing.*;
import java.awt.*;

public class TextAreaExample {
    public static void main(String[] args) {
        JFrame frame = new JFrame("JTextArea 示例");
        JTextArea textArea = new JTextArea(10, 30);
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        
        JScrollPane scrollPane = new JScrollPane(textArea);
        frame.add(scrollPane, BorderLayout.CENTER);
        
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }
}

JTextField

JTextField 是 Java Swing 中用于单行文本输入的组件。它非常适合用于收集短文本数据,如用户名、密码、搜索框等。以下是 JTextField 的一些主要特点和用法:

主要特点

  1. 单行输入JTextField 设计用于输入单行文本,适合处理简单的数据输入。

  2. 可编辑性:用户可以点击文本框并输入或编辑文本。

  3. 占位符文本:可以设置提示文本,引导用户输入所需格式的信息。

  4. 事件处理:支持键盘事件,可以添加监听器来处理文本更改事件、焦点事件等。

  5. 限制输入:可以通过设置文档过滤器或自定义逻辑来限制用户输入的字符类型。

常用方法

  • 构造函数

    JTextField textField = new JTextField(columns);
    

    可以指定文本框的列数,影响其宽度。

  • 设置文本

    textField.setText("初始文本");
    
  • 获取文本

    String text = textField.getText();
    
  • 清空文本

    textField.setText("");
    
  • 设置可编辑性

    textField.setEditable(false); // 设置为不可编辑
    
  • 添加事件监听

    textField.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            // 处理事件
        }
    });
    

示例代码

下面是一个简单的示例,展示如何创建一个包含 JTextField 的 GUI 应用:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class TextFieldExample {
    public static void main(String[] args) {
        JFrame frame = new JFrame("JTextField 示例");
        JTextField textField = new JTextField(20); // 创建一个宽度为20列的文本框
        
        JButton button = new JButton("提交");
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                String inputText = textField.getText(); // 获取输入文本
                JOptionPane.showMessageDialog(frame, "您输入的文本是: " + inputText);
            }
        });
        
        JPanel panel = new JPanel();
        panel.add(textField);
        panel.add(button);
        
        frame.getContentPane().add(panel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }
}

JFrame

JFrame 是 Java Swing 中用于创建窗口的主要组件。它代表一个应用程序的主窗口,用户可以在其中添加各种其他组件(如按钮、文本框等)。以下是 JFrame 的一些主要特点和用法:

主要特点

  1. 窗口管理JFrame 提供了一个可见的界面,用户可以通过它与应用程序交互。

  2. 标题栏:可以为窗口设置标题,这将显示在窗口的标题栏中。

  3. 关闭操作:可以设置窗口关闭时的行为,比如退出应用程序或隐藏窗口。

  4. 布局管理:支持多种布局管理器,可以控制组件在窗口中的排列方式。

  5. 菜单栏:可以为窗口添加菜单栏,以提供更多功能选项。

常用方法

  • 构造函数

    JFrame frame = new JFrame("窗口标题");
    
  • 设置默认关闭操作

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 退出程序
    
  • 设置大小

    frame.setSize(400, 300); // 设置宽度和高度
    
  • 设置可见性

    frame.setVisible(true); // 显示窗口
    
  • 添加组件

    frame.add(component); // 向窗口添加组件
    
  • 设置布局

    frame.setLayout(new FlowLayout()); // 设置流式布局
    

示例代码

下面是一个简单的示例,展示如何创建一个基本的 JFrame 窗口并在其中添加一些组件:

import javax.swing.*;
import java.awt.*;

public class JFrameExample {
    public static void main(String[] args) {
        // 创建窗口
        JFrame frame = new JFrame("JFrame 示例");
        
        // 设置默认关闭操作
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        // 设置窗口大小
        frame.setSize(400, 300);
        
        // 设置布局
        frame.setLayout(new FlowLayout());
        
        // 添加组件
        JLabel label = new JLabel("欢迎使用 JFrame!");
        JButton button = new JButton("点击我");
        
        frame.add(label);
        frame.add(button);
        
        // 设置窗口可见
        frame.setVisible(true);
    }
}

JPanel

JPanel 是 Java Swing 中一个重要的容器组件,用于组织和管理其他组件。它可以用来分组相关的组件,并提供灵活的布局管理选项。以下是 JPanel 的一些主要特点和用法:

主要特点

  1. 容器JPanel 可以包含多个组件(如按钮、文本框等),并能有效地管理它们的布局。

  2. 布局管理:可以使用不同的布局管理器(如 FlowLayoutBorderLayoutGridLayout 等)来控制组件的排列方式。

  3. 可绘制性:你可以重写 paintComponent 方法,在 JPanel 上自定义绘制图形或背景。

  4. 轻量级组件JPanel 是一个轻量级组件,不会直接影响 GUI 的性能,适合用于构建复杂界面。

  5. 支持透明背景:通过设置透明度,可以实现更复杂的视觉效果。

常用方法

  • 构造函数

    JPanel panel = new JPanel();
    
  • 设置布局

    panel.setLayout(new FlowLayout()); // 设置为流式布局
    
  • 添加组件

    panel.add(component); // 向面板添加组件
    
  • 设置背景颜色

    panel.setBackground(Color.LIGHT_GRAY); // 设置背景颜色
    
  • 绘制自定义内容

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        // 自定义绘制代码
    }
    

示例代码

下面是一个简单的示例,展示如何创建一个 JPanel 并在其中添加一些组件:

import javax.swing.*;
import java.awt.*;

public class JPanelExample {
    public static void main(String[] args) {
        // 创建主窗口
        JFrame frame = new JFrame("JPanel 示例");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 300);
        
        // 创建面板
        JPanel panel = new JPanel();
        panel.setLayout(new FlowLayout());
        panel.setBackground(Color.LIGHT_GRAY); // 设置背景颜色
        
        // 添加组件
        JLabel label = new JLabel("欢迎使用 JPanel!");
        JButton button = new JButton("点击我");
        
        panel.add(label);
        panel.add(button);
        
        // 将面板添加到窗口
        frame.add(panel);
        
        // 显示窗口
        frame.setVisible(true);
    }
}

JScrollPane

JScrollPane 是 Java Swing 中用于提供滚动功能的组件,它允许用户在一个固定大小的区域中查看比该区域大得多的内容。通常,JScrollPane 主要用于包含长文本或大型图像等内容,以便用户能够通过滚动条进行查看。

主要特点

  1. 自动生成滚动条:当内容超出可视区域时,JScrollPane 会自动添加水平和/或垂直滚动条。

  2. 灵活的内容容器:可以将任何组件(如 JPanelJTextArea 等)放入 JScrollPane 中,从而使其支持滚动。

  3. 控制滚动条的行为:可以设置滚动条的政策(例如总是显示、只在需要时显示等)。

  4. 支持平滑滚动:可以通过程序控制滚动位置,实现更好的用户体验。

常用方法

  • 构造函数

    JScrollPane scrollPane = new JScrollPane();
    
  • 设置内容

    scrollPane.setViewportView(component); // 设置可滚动的组件
    
  • 设置滚动条策略

    scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); // 始终显示垂直滚动条
    
  • 获取滚动条

    JScrollBar verticalScrollBar = scrollPane.getVerticalScrollBar(); // 获取垂直滚动条
    

示例代码

下面是一个简单的例子,展示如何使用 JScrollPane 来创建一个带有滚动条的文本区域:

import javax.swing.*;

public class JScrollPaneExample {
    public static void main(String[] args) {
        // 创建主窗口
        JFrame frame = new JFrame("JScrollPane 示例");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 300);
        
        // 创建文本区域
        JTextArea textArea = new JTextArea(20, 30); // 20 行,30 列
        for (int i = 1; i <= 100; i++) {
            textArea.append("行 " + i + "\n"); // 添加内容
        }
        
        // 创建滚动面板并添加文本区域
        JScrollPane scrollPane = new JScrollPane(textArea);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); // 始终显示垂直滚动条
        
        // 将滚动面板添加到窗口
        frame.add(scrollPane);
        
        // 显示窗口
        frame.setVisible(true);
    }
}

👉🏻多线程

Java 的多线程是指在一个程序中同时执行多个线程,以提高程序的效率和响应能力。多线程可以让 CPU 更有效地利用,特别是在处理 I/O 操作或计算密集型任务时。

1. 线程的基本概念

  • 线程:线程是程序执行的最小单位,一个 Java 应用程序至少有一个主线程。
  • 进程:进程是系统中运行的程序的实例,它可以包含一个或多个线程。

2. 创建线程的方法

Java 提供了两种创建线程的方式:

2.1 继承 Thread
class MyThread extends Thread {
    public void run() {
        System.out.println("线程正在运行");
    }
}

public class Main {
    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start(); // 启动线程
    }
}
2.2 实现 Runnable 接口
class MyRunnable implements Runnable {
    public void run() {
        System.out.println("线程正在运行");
    }
}

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable());
        thread.start(); // 启动线程
    }
}

3. 线程的生命周期

线程的生命周期包括以下几个状态:

  • 新建(New):线程被创建,但还未启动。
  • 就绪(Runnable):线程已启动,并在等待 CPU 调度。
  • 运行(Running):线程正在执行。
  • 阻塞(Blocked):线程在等待锁资源。
  • 等待(Waiting):线程在等待其他线程的通知或完成。
  • 终止(Terminated):线程运行结束。

4. 线程同步

由于多个线程可能会访问共享资源,导致数据不一致,因此需要使用线程同步来控制对共享资源的访问。

4.1 使用 synchronized 关键字
class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }
}
4.2 使用 Lock 接口
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class Counter {
    private int count = 0;
    private Lock lock = new ReentrantLock();

    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }

    public int getCount() {
        return count;
    }
}

5. 线程通信

Java 提供了线程间通信机制,可以使用 wait()notify()notifyAll() 方法。

class SharedResource {
    private int value;

    public synchronized void produce(int newValue) {
        value = newValue;
        notify(); // 通知消费者线程
    }

    public synchronized int consume() throws InterruptedException {
        while (value == 0) {
            wait(); // 等待生产者线程
        }
        return value;
    }
}

6. 线程池

为了提高性能并管理线程的生命周期,Java 提供了线程池。通过 Executors 类可以方便地创建和管理线程池。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(3);
        
        for (int i = 0; i < 5; i++) {
            executor.submit(() -> {
                System.out.println("线程 " + Thread.currentThread().getName() + " 正在执行");
            });
        }
        
        executor.shutdown(); // 关闭线程池
    }
}

如上便是本期的所有内容了,如果喜欢并觉得有帮助的话,希望可以博个点赞+收藏+关注🌹🌹🌹❤️ 🧡 💛,学海无涯苦作舟,愿与君一起共勉成长
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值