_生产者和消费者案例<代码有误,正在调试>
-
生产者消费者案例中包含的类:
- 奶箱类(Box):定义一个成员变量,表示第x瓶奶,提供存储牛奶和获取牛奶的操作
- 生产者类(Producer):实现Runnable接口,重写run()方法,调用存储牛奶的操作
- 消费者类(Customer):实现Runnable接口,重写run()方法,调用存储牛奶的操作
- 测试类(BoxDemo):里面有main方法,main方法中的代码步骤如下:
- 创建奶箱对象,这是共享数据区域
- 创建消费者对象,把奶箱对象作为构造方法参数传递,因为在这个类中需要调用存储牛奶的操作
- 创建消费者对象,把奶箱对象作为构造方法参数传递,因为在这个类中需要调用存储牛奶的操作
- 创建两个线程,分别把生产者对象和消费者对象作为构造方法参数传递
- 启动线程
-
package demo20; public class Application { public static void main(String[] args) { /* 生产者消费者案例中包含的类: - 奶箱类(Box):定义一个成员变量,表示第x瓶奶,提供存储牛奶和获取牛奶的操作 - 生产者类(Producer):实现Runnable接口,重写run()方法,调用存储牛奶的操作 - 消费者类(Customer):实现Runnable接口,重写run()方法,调用存储牛奶的操作 - 测试类(BoxDemo):里面有main方法,main方法中的代码步骤如下: - 创建奶箱对象,这是共享数据区域 - 创建消费者对象,把奶箱对象作为构造方法参数传递,因为在这个类中需要调用存储牛奶的操作 - 创建消费者对象,把奶箱对象作为构造方法参数传递,因为在这个类中需要调用存储牛奶的操作 - 创建两个线程,分别把生产者对象和消费者对象作为构造方法参数传递 - 启动线程 */ Box b = new Box(); // 创建生产者和消费者对象 Producer producer = new Producer(b); Customer customer = new Customer(b); Thread t1 = new Thread(producer); Thread t2 = new Thread(customer); // 启动线程 t1.start(); t2.start(); } } ------------------------------------------------- package demo20; public class Producer implements Runnable { private Box b ; public Producer(Box b) { this.b = b; } @Override public void run() { for (int i = 1; i <= 5; i++) { b.put(i); } } } ------------------------------------------ package demo20; public class Customer implements Runnable{ private Box b; public Customer(Box b) { this.b = b; } @Override public void run() { b.get(); } } ----------------------------------------- package demo20; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Box { /* 奶箱类(Box):定义一个成员变量,表示第x瓶奶,提供存储牛奶和获取牛奶的操作 */ private int milk; private int milkBox = 0; Lock lock = new ReentrantLock(); // 定义一个成员变量,表示奶箱的状态,默认为关闭状态 private boolean state = false; public synchronized void put(int milk) { this.milk = milk; if (milkBox < 1) { milkBox++; System.out.println("送奶工放入第" + milk + "瓶牛奶"); System.out.println("此时奶箱中有"+milkBox+"瓶牛奶"); // 唤醒所有线程 lock.notifyAll(); }else { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } public synchronized void get() { this.milk = milk; if (milkBox >= 1) { milkBox--; System.out.println("客人取出第" + milk + "瓶牛奶"); System.out.println("此时奶箱中有"+milkBox+"瓶牛奶"); // 唤醒所有线程 lock.notifyAll(); }else { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } ==========================================
_IP地址
- 常用命令:(在Dos命令窗口中)
- ipconfig:查看本机的IP地址
- ping IP地址:检查网络是否连通
_InetAddress
-
为了方便我们对IP地址的获取和操作,java提供了一个类InetAddress供我们使用
-
InetAddress:此类表示Internet协议(IP)地址
-
方法名 说明 static InetAddress getByName(String host) 确定主机名称的IP地址。主机名称可以是机器名称,也可以是IP地址 String getHostName() 获取IP地址的主机名称 String getHostAddress() 返回文本显示中的IP地址字符串 -
package demo21; import java.net.InetAddress; import java.net.UnknownHostException; public class IP_Demo_01 { public static void main(String[] args) { /* 1. 为了方便我们对IP地址的获取和操作,java提供了一个类InetAddress供我们使用 2. InetAddress:此类表示Internet协议(IP)地址 3. static InetAddress getByName(String host) 确定主机名称的IP地址。主机名称可以是机器名称,也可以是IP地址 String getHostName() 获取IP地址的主机名称 String getHostAddress() 返回文本显示中的IP地址字符串 */ try { InetAddress address = InetAddress.getByName("192.169.10.3"); String IP = address.getHostAddress(); String name = address.getHostName(); System.out.println("主机名称:"+name); System.out.println("IP地址:" + IP); } catch (UnknownHostException e) { e.printStackTrace(); } } } ========================================== 主机名称:192.169.10.3 IP地址:192.169.10.3 Process finished with exit code 0
_UDP发送数据
-
发送数据的步骤:
- 创建发送端的Socket对象(DatagramSocket) // socket:插座
- DatagramSocket()
- 创建数据,并把数据打包
- DatagramPacket(byte[] buf , int length , InetAddress , int port)
- 调用DatagramSocket对象的方法发送数据
- void send(DatagramPacket p)
- 关闭发送端
- void close()
- 创建发送端的Socket对象(DatagramSocket) // socket:插座
-
package demo21; import java.io.IOException; import java.net.*; public class UDP_Demo_01 { public static void main(String[] args) { /* 发送数据的步骤: - 创建发送端的Socket对象(DatagramSocket) // socket:插座 - DatagramSocket() - 创建数据,并把数据打包 - DatagramPacket(byte[] buf , int length , InetAddress , int port) - 调用DatagramSocket对象的方法发送数据 - void send(DatagramPacket p) - 关闭发送端 - void close() */ /* public class DatagramSocket 此类表示用于发送和接收数据报数据包的套接字。 数据报套接字是分组传送服务的发送或接收点。 在数据报套接字上发送或接收的每个数据包都被单独寻址和路由。 从一个机器发送到另一个机器的多个分组可以不同地路由,并且可以以任何顺序到达。 */ try { DatagramSocket ds = new DatagramSocket(); // 创建数据,并把数据打包 // - DatagramPacket(byte[] buf , int length , InetAddress , int port) byte[] bytes = "hello,Internet,I am coming".getBytes(); int length = bytes.length; InetAddress inetAddress = InetAddress.getByName("198.168.10.3"); // 打包 DatagramPacket dp = new DatagramPacket(bytes, length, inetAddress, 10086); // 调用DatagramSocket对象的方法发送数据 ds.send(dp); // 关闭发送端 ds.close(); } catch (SocketException e) { e.printStackTrace(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } =================================== Process finished with exit code 0
_UDP接收数据
-
接收数据的步骤:
- 创建接收端的Socket对象(DatagramSocket)
- DatagramSocket(int port)
- 创建一个数据包,用于接收数据
- DatagramPacket(byte[] buf ,int length)
- 解析数据包,并把数据在控制台显示
- byte[] getData()
- int getLength()
- 关闭接收端
- void close
- 创建接收端的Socket对象(DatagramSocket)
-
package demo21; import java.io.IOException; import java.net.*; public class Send_Demo { public static void main(String[] args) { /* 发送数据的步骤: - 创建发送端的Socket对象(DatagramSocket) // socket:插座 - DatagramSocket() - 创建数据,并把数据打包 - DatagramPacket(byte[] buf , int length , InetAddress , int port) - 调用DatagramSocket对象的方法发送数据 - void send(DatagramPacket p) - 关闭发送端 - void close() */ /* public class DatagramSocket 此类表示用于发送和接收数据报数据包的套接字。 数据报套接字是分组传送服务的发送或接收点。 在数据报套接字上发送或接收的每个数据包都被单独寻址和路由。 从一个机器发送到另一个机器的多个分组可以不同地路由,并且可以以任何顺序到达。 */ try { DatagramSocket ds = new DatagramSocket(); // 创建数据,并把数据打包 // - DatagramPacket(byte[] buf , int length , InetAddress , int port) byte[] bytes = "hello,Internet,I am coming".getBytes(); int length = bytes.length; InetAddress inetAddress = InetAddress.getByName("192.168.10.3"); // 打包 DatagramPacket dp = new DatagramPacket(bytes, length, inetAddress, 10086); // 调用DatagramSocket对象的方法发送数据 ds.send(dp); // 关闭发送端 ds.close(); } catch (SocketException e) { e.printStackTrace(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } ------------------------------------------- package demo21; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException; public class Receive_Demo { public static void main(String[] args) { /* 接收数据的步骤: - 创建接收端的Socket对象(DatagramSocket) - DatagramSocket(int port) - 创建一个数据包,用于接收数据 - DatagramPacket(byte[] buf ,int length) - 解析数据包,并把数据在控制台显示 - byte[] getData() - int getLength() - 关闭接收端 - void close */ try { // 创建接收端的Socket对象(DatagramSocket) DatagramSocket ds = new DatagramSocket(10086); // 创建一个数据包,用于接收数据 // DatagramPacket(byte[] buf ,int length) byte[] bytes = new byte[1024]; int length = bytes.length; DatagramPacket dp = new DatagramPacket(bytes, length); // 调用DatagramSocket对象的方法来接收数据 /* public void receive(DatagramPacket p) throws IOException 从此套接字接收数据报包。 当此方法返回时, DatagramPacket的缓冲区将填充接收到的数据。 数据包数据包还包含发送者的IP地址和发件人机器上的端口号。 */ ds.receive(dp); // 解析数据包,并把数据在控制台显示 // 返回数据缓冲区 // byte[] getData() byte[] data = dp.getData(); // 返回接收数据的长度 int len = dp.getLength(); // 将byte类型的接收数据转换成String类型的数据 /* public String(byte[] bytes, int offset, int length) 通过使用平台的默认字符集解码指定的字节子阵列来构造新的String 。 新的String的长度是字符集的函数,因此可能不等于子数组的长度。 指定字节在默认字符集中无效时,此构造函数的行为是未指定的。 当需要更多的解码过程控制时,应使用CharsetDecoder类。 */ String dataString = new String(data, 0, len); // 将接收到的数据显示到控制台上 System.out.println("接收到的数据:" + dataString); // 关闭接收端 ds.close(); } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } ============================================== 接收到的数据:hello,Internet,I am coming Process finished with exit code 0