多线程/网络编程 一、线程概述 1、进程:当前正在运行的程序,一个应用程序在内存中的执行区域。 2、线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。 由进程就可以引出多线程概述: 一个程序运行后至少有一个进程,一个进程中可以包含多个线程 二、多线程的实现方式 实现方式一:继承Thread类 将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。 Thread类属于java.lang包下,所以使用时不需要进行导包 例如: class Student extends Thread{ @Override public void run(){ System.out.println(getName()+“运行”); } } 测试方法 class ThreadDemo{ public static void mian(String[] args){ //创建 Student s = new Student(); S.getName();//获取线程名 S.setName(“线程一”);//修改线程名 S.start();//启动线程 } } 实现方式二:实现接口Runnable 声明实现 Runnable 接口的类。该类然后实现 run 方法。然后创建Runnable的子类对象,传入到某个线程的构造方法中,开启线程。(此方法为主要的方法,可以和继承配合使用). 创建线程的步骤。 1、定义类实现Runnable接口。 2、覆盖接口中的run方法。。 3、创建Thread类的对象 4、将Runnable接口的子类对象作为参数传递给Thread类的构造函数。 5、调用Thread类的start方法开启线程。 例如: class Student implements Runnable{ @Override public void run{ System.out.println(Thread.currentThread().getName()+”运行”) //currententThread() 返回对当前正在执行的线程对象的引用 } } //测试类 class RunnableDemo{ public static void main(String[] args){ Student ss = new Student(); Thread t = new Thread(ss); t.setName(“线程一”); t.start();//线程启动 } } 三、多线程的安全问题解决 同步代码块 synchronized:同步(锁),可以修饰代码块和方法,被修饰的代码块和方法一旦被某个线程访问,则直接锁住,其他的线程将无法访问. Synchronized(锁对象){ //需要同步的代码块 } 锁对象必须是被线程所共享的对象.例如 Object lock = new Object(); 或者字节码对象 所对象的注意事项 非静态同步方法的锁对象是this 静态的同步方法的锁对象是当前类的字节码 四、面向网络 网络编程三要素 1、IP地址有InetV4Address(8字节) & InetV6Address(32字节) 2、端口号 3、通信协议(UDP、TCP) UDP:不需要建立连接,大小限制64KB以内,传输快,不可靠 TCP:需要建立键连接,传输慢一点,安全可靠; 获取主机名或者IP地址 InetAddress address = InetAddress.getByName("itheima"); InetAddress address = InetAddress.getByName("192.168.1.107");//ip地址是唯一的 String hostAddress = address.getHostAddress();//192.168.1.107 返回IP地址 String hostName = address.getHostName();//itheima 返回主机名 UDP格式(客户端) public class SendDemo { public static void main(String[] args) throws IOException { //创建发送端Socket对象 DatagramSocket ds = new DatagramSocket(); //创建数据并打包 /* * DatagramPacket :此类表示数据报包 * 数据 byte[] * 设备的地址 ip * 进程的地址 端口号 DatagramPacket(byte[] buf, int length, InetAddress address, int port) */ String s = "hello udp,im comming!"; byte[] bys = s.getBytes(); int length = bys.length; InetAddress address = InetAddress.getByName("itheima");//发送给当前设备 int port = 8888; //打包 DatagramPacket dp = new DatagramPacket(bys,length,address,port); //发送数据 ds.send(dp); //释放资源 ds.close(); } } UDP(接收端) public class ReceiveDemo { public static void main(String[] args) throws IOException { //创建接收端Socket对象 DatagramSocket ds = new DatagramSocket(8888); //接收数据 //DatagramPacket(byte[] buf, int length) byte[] bys = new byte[1024]; DatagramPacket dp = new DatagramPacket(bys,bys.length); System.out.println(1); ds.receive(dp);//阻塞 System.out.println(2); //解析数据 //InetAddress getAddress() : 获取发送端的IP对象 InetAddress address = dp.getAddress(); //byte[] getData() :获取接收到的数据,也可以直接使用创建包对象时的数组 byte[] data = dp.getData(); //int getLength() :获取具体收到数据的长度 int length = dp.getLength(); //输出数据 System.out.println("sender ---> " + address.getHostAddress()); //System.out.println(new String(data,0,length)); System.out.println(new String(bys,0,length)); //释放资源 ds.close(); } } 注意事项:1/ 端口号如果不一致,不会报错,但是接收不到数据 2/接收端的端口不可重复. TCP(客户端) public class ClientDemo { public static void main(String[] args) throws IOException { //创建发送端Socket对象(创建连接) Socket s = new Socket(InetAddress.getByName("itheima"),10086); //获取输出流对象 OutputStream os = s.getOutputStream(); //发送数据 String str = "hello tcp,im comming!!!"; os.write(str.getBytes()); //释放资源 //os.close(); s.close(); } } TCP(服务器端) public class ServerDemo { public static void main(String[] args) throws IOException { //创建接收端Socket对象 ServerSocket ss = new ServerSocket(10086); //监听(阻塞) Socket s = ss.accept(); //获取输入流对象 InputStream is = s.getInputStream(); //获取数据 byte[] bys = new byte[1024]; int len;//用于存储读到的字节个数 len = is.read(bys); //输出数据 InetAddress address = s.getInetAddress(); System.out.println("client ---> " + address.getHostName()); System.out.println(new String(bys,0,len)); //释放资源 s.close(); //ss.close(); }
|