JAVA复习四——MultiThread、JDBC、Network programming

发布时间:2024年01月02日

这三章节基本知识点不是很多,重点是代码的编写。

接下来我将以三道例题来分别讲解这三个知识点

一、多线程

例:

创建一个模拟铁路售票系统,要求创建10个线程模拟10个售票点,每个售票点不停地卖票, 每张票有一个 id(从 0 开始不断增加)。

要求:

1) 每个售票点销售的票 id 不能重复。

2) 一共只有 200 张火车票,售完为止。

3) 程序显示的结果类似于:

售票点 1 正在售出火车票 No.1

售票点 2 正在售出火车票 No.2

售票点 1 正在售出火车票 No.3

售票点 5 正在售出火车票 No.4

售票点 8 正在售出火车票 No.5

售票点 1 正在售出火车票 No.6

售票点 3 正在售出火车票 No.7

售票点 9 正在售出火车票 No.200

售票点 1 售罄

售票点 2 售罄

...

这个例题涉及的相关知识面还挺广的。

代码中有疑问的地方,请自行移步学习:菜鸟教程:Java多线程编程

package test;

import java.util.concurrent.atomic.AtomicInteger;

//首先将这个项目定义为一个多线程类
//其次,将所有线程都会用到的变量定义在进程中,且加上final关键字,防止线程私自改变这些变量;
//然后,我们给每个线程定义了ThreadID来区分不同的线程
//最后,synchronized关键字的使用,同步加锁。
//学过操作系统的同学应该都知道加锁的概念。
//这个关键字就是:我在使用某个对象的时候给这个对象加锁,其余线程全部不能使用这个变量,
//等我释放之后其他线程才能使用。
//使用这个关键字,来预防多个线程同时卖出同一张票的情况。

public class MultiThread implements Runnable {
    public static final int Totaltickets=200;
   /*AtomicInteger对象,本质上还是个int,但是这个对象有一个自增函数。因为该对象加上了final关键 
    字,而我们又想让其+1,所以就采用AtomicInteger关键字来实现。*/
    public static final AtomicInteger currentTicket=new AtomicInteger(0);
    public static final Object lock=new Object();
    private final int threadID;

    //构造函数,指定ThreadID,且添加final关键字,这个值是进程赋予线程的。线程不能对其进行改变
    public MultiThread(int Id){
        this.threadID=Id;
    }

    @Override
    public  void run(){
       while(true){
           try{
           synchronized(lock){
               int currentTicket=MultiThread.currentTicket.getAndIncrement();
               //得到当前的票数
               if(currentTicket<MultiThread.Totaltickets){
                   System.out.println("售票口"+threadID+" 售出票号:"+currentTicket);
               }
               else{
                   System.out.println("售票口"+threadID+"已售罄");break;
               }
           }
           Thread.sleep(100);
       }catch (Exception e){e.printStackTrace();}
       }
    }

    public static void main(String[] args) {
    //创建十个线程并运行
        for (int i = 0; i < 10; i++) {
            new Thread(new MultiThread(i)).start();
        }
    }
}

二、JDBC

例:

JDBC大家应该用的都比教多,随便写个JavaWeb或者数据库的实验都得用到。但是这里我们直接使用Java代码与数据库进行交互,不引入mybatis等其他的框架。这里可能题目有点小问题,应该是在数据库中创建数据表bookstore。

大致流程:
(1)连接数据库

连接数据库,使用DriverManager对象连接数据库,

通过connection创建pre对象,

(2)插入数据

使用preparedstatement的executeQuary()函数插入数据

(3)读取数据

通过connection创建statement对象。

通过statement对象执行sql语句

查询语句的返回值是ResultSet对象

遍历rs对象进行输出

下列代码不保证百分百运行,因为可能还需要一些额外的数据库的文件配置。

package test;

import java.sql.*;

public class JdbCode {
    public static void main(String[] args) {
       Class.forName("com.mysql.cj.jdbc.Driver");
        try{
//连接数据库
          Connection con= DriverManager.getConnection("jdbc:mysql://localhost:3306?DB_NAME&&username='root'&&password='root'");
//设置执行语句
           String create= "CREATE TABLE IF NOT EXISTS bookstore (VARCHAR(20) store_name PRIMARY KEY,INT Sales, VARCHAR(20) Date)";
//创建stetement对象,建立数据表
           Statement createTable=con.createStatement();
           createTable.executeQuery(create);
           PreparedStatement pre=con.prepareStatement("INSERT INTO bookstore (VARCHAR(20) store_name,INT Sales, VARCHAR(20) Date) VALUS(?,?,?)");
//使用preparedstatement对象插入数据
            insert("Los Angeles",1500,"1999-01-09",pre);
            insert("San Diego",250,"1999-01-01",pre);
            insert("Los Angeles",300,"1999-01-02",pre);
            insert("Boston",700,"1999-01-05",pre);
//创建statement对象,读取数据表中的数据,返回值为ResultSet         
           ResultSet rs=con.createStatement().executeQuery("SELETC * FROM bookstore");
           while(rs.next()){
               String name=rs.getString(1);
               int sale=rs.getInt(2);
               String date=rs.getString(3);
               System.out.printf("10_s%",name);
               System.out.printf("10_d%",sale);
               System.out.printf("10_s%",date);
           }
        }catch (Exception e){e.printStackTrace();}
    }

    public static void insert(String store_name,int Sales,String Date,PreparedStatement pre) throws SQLException {
        pre.setString(1,store_name);
        pre.setInt(2,Sales);
        pre.setString(3,Date);
        pre.executeBatch();
        pre.clearParameters();
    }
}

三、网络编程

网络编程起码要有两个类,一个服务端,一个客户端。而且服务端多数情况下要写为多线程,以同时服务多个客户端。甚至可能一个服务端要分两个线程,以便在接受消息的时候发送消息。所以服务端一般在main函数里面创建socket对象,表示监听接口,可以创建多个。然后通过多线程来同步开启消息的接受和发送。

先简单说下流程吧,

(1)服务器创建一个ServerSocket对象并使用accept()函数监听一个端口;当客户端访问该端口时,accept函数返回一个Socket对象。

(2)客户端使用Socket对象直接根据URL和端口号连接服务端。

(3)连接成功后,客户端和服务端之间就可以通过socket对象进行通信。socket对象同时具有输入输出流,且socket对象可以确定本地以及对方的Adress。

例题:

使用控制台,写一个内网聊天工具,能够同时和另一个人接受并发送信息。(已知双方 的 ip 地址和端口号,不要求同时与多人聊天)注:(这一段代码实现了多人同步聊天,但是只能是服务器同步和多个客户端聊天,但是需要多建立几个服务器才可。这里只建立了一个)

服务端:

package chatApp;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;


public class Server {
    private static  int MAX_THREADS=10;
    public  static  int CURRENT_THREAD=0;

    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket=new ServerSocket(1234);
        //在服务器程序启动时,它将在端口1234上创建一个ServerSocket对象,用于监听来自客户端的连接请求。
        // 一旦有客户端尝试连接到该端口,ServerSocket将接受连接并返回一个Socket对象,该对象可用于与客户端进行通信。
        // 在这之后,服务端可以使用该Socket对象与客户端进行数据交换。
        System.out.println("等待客户端连接......");
        Socket clientSocket=serverSocket.accept();
        System.out.println("客户端已连接");

        //启动发送消息的线程;
        new Thread(new SendMessage(clientSocket)).start();
        //启动接受信息的线程
        new Thread(new ReceiveMessage(clientSocket)).start();
    }


    static class ReceiveMessage implements Runnable{
//接收消息的线程
        private  Socket socket;
        public ReceiveMessage(Socket socket){
            this.socket=socket;
        }

        @Override
        public void run() {
            try {
                //通过socket对象获取输入流,这是用于从客户端接收数据的输入流。
                BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String line=bufferedReader.readLine();
                //这个循环会不断地从输入流中读取新的行,然后在控制台上打印服务器收到的消息。当客户端关闭连接时,
                while ((line = bufferedReader.readLine()) != null) {
                    System.out.println("客户端: " + line);
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }


    static class SendMessage implements Runnable{
//发送消息的线程
        private Socket socket;
        public  SendMessage(Socket socket){
            this.socket=socket;
        }
        @Override
        public void run() {
            try {
                //获取到与客户端连接的输出流,这里用于向客户端发送数据。
                PrintWriter printWriter = new PrintWriter(socket.getOutputStream(),true);
                //写入流,用于从控制台读取信息
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader( System.in));
                String line;

                //读取控制台输入的内容
                while ((line = bufferedReader.readLine()) != null) {
                //然后将控制台读取的内容通过socket的OutputStream输出给客户端
                    printWriter.println(line);
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

}

客户端:

package chatApp;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class Clienter {

    public static void main(String[] args) {
            try {
                Socket socket = new Socket("localhost", 1234);
                // 创建并启动接收消息的线程
               new Thread(new ReceiveMessage(socket)).start();
              
                // 创建并启动发送消息的线程
               new Thread(new SendMessage(socket)).start();
           
            } catch (IOException e) {
                e.printStackTrace();
            }
    }

    static class ReceiveMessage implements Runnable {
        private Socket socket;
        public ReceiveMessage(Socket socket) {
            this.socket = socket;
        }
        @Override
        public void run() {
            try {
                BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String line;
                while ((line = reader.readLine()) != null) {

                    System.out.println("服务器: " + line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    static class SendMessage implements Runnable {
        private Socket socket;
        public SendMessage(Socket socket) {
            this.socket = socket;
        }
        @Override
        public void run() {
            try {
                PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
                BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));

                String line;
                while ((line = consoleReader.readLine()) != null) {
                    writer.println(line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

文章来源:https://blog.csdn.net/lyhizjj/article/details/135344947
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。