Java 线程和网络编程

线程

线程优先级

提高线程优先执行的可能

    1~10  1最小  10最大  默认时5
    setPriority(int newPriority) 改变这个线程的优先级。

static int MAX_PRIORITY //一个线程可以拥有的最高优先级。
static int MIN_PRIORITY // 一个线程可以拥有的最低优先级。
static int NORM_PRIORITY // 分配给线程的默认优先级。

    public class ThreadDemo01 implements Runnable{
        public static void main(String[] args) {
            ThreadDemo01 demo = new ThreadDemo01();
            Thread th1 = new Thread(demo,"A");
            Thread th2 = new Thread(demo,"B");
            Thread th3 = new Thread(demo,"C");

            //设置优先级
            th1.setPriority(Thread.MIN_PRIORITY);  
            th3.setPriority(10);

            th1.start();  
            th2.start();
            th3.start();

            //查看优先级
            System.out.println(th1.getPriority());
            System.out.println(th2.getPriority());
            System.out.println(th3.getPriority());
        }

        @Override
        public void run() {		         
            System.out.println(Thread.currentThread().getName());
        }
    }

线程死锁

死锁及解决方案
    class Lipstick{ 
    }
    class Mirror{ 
    }

    class Makeup extends Thread { 
        int flag; 
        String girl; 
        static Lipstick lipstick=new Lipstick(); 
        static Mirror mirror= new Mirror(); 

        @Override 
        public void run() {  
            doMakeup(); 
        }

        void doMakeup(){
            if(flag==0){ 
                synchronized (lipstick) { 
                    System.out.println(girl+"拿着口红!"); 
                    try {
                        Thread.sleep(1000); 
                    } catch (InterruptedException e) { 
                        e.printStackTrace(); 
                    }
                    synchronized (mirror) { 
                        System.out.println(girl+"拿着镜子!"); 
                    } 
                } 
            }else{
                synchronized (mirror) { 
                    System.out.println(girl+"拿着镜子!"); 
                    try {
                        Thread.sleep(2000); 
                    } catch (InterruptedException e) { 
                        e.printStackTrace(); 
                    }
                    synchronized (lipstick) { 
                        System.out.println(girl+"拿着口红!"); 
                    } 
                } 
            } 
        } 
    }

    public class TestDeadLock { 
        public static void main(String[] args) { 
            Makeup m1 = new Makeup(); 
            m1.girl="大丫"; 
            m1.flag=0; 
            Makeup m2 = new Makeup(); 
            m2.girl="小丫"; 
            m2.flag=1; 
            m1.start(); 
            m2.start(); 
        } 
    }

如何解决死锁问题:

  • 往往是程序逻辑的问题。需要修改程序逻辑。

  • 尽量不要同时持有两个对象锁。 如修改成如下:

    void doMakeup(){ 
        if(flag==0){ 
            synchronized (lipstick) { 
                System.out.println(girl+"拿着口红!"); 
                try {
                    Thread.sleep(1000);
                    } catch (InterruptedException e) { 
                        e.printStackTrace(); 
                    } 
            }
            synchronized (mirror) { 
                System.out.println(girl+"拿着镜子!"); 
            } 
            else{
                synchronized (mirror) { 
                    System.out.println(girl+"拿着镜子!"); 
                    try {
                        Thread.sleep(2000); 
                    } catch (InterruptedException e) { 
                        e.printStackTrace(); 
                } 
            }
                synchronized (lipstick) { 
                    System.out.println(girl+"拿着口红!"); 
                } 
            } 
        } 
    }

线程通信

生产者消费者模式

wait() 等待 当一个线程wait,会进入到对象的等待池中,等待被唤醒

  • 让出cpu的资源,让出 对象锁资源

notify() 唤醒随机一个 唤醒对象等待池中的线程,被唤醒的线程会进入到就绪状态,满足使用条件才可以使用

notifyAll() 唤醒全部

  • 必须要使用在一个同步的环境下
    public class Demo03 {
        public static void main(String[] args) {
            Street street = new Street();
            //人线程  车线程
            new Thread(new Person(street)).start();
            new Thread(new Car(street)).start();
        }
    }

    //街道资源
    class Street{
        //红绿灯
        private boolean flag = false;

        //东西->人 -->false
        public void we() {
            //true-->wait()
            if(flag != false) {
                try {
                    this.wait();  //当前线程进入到this对象的等待池中
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }else {   //人走
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("人走......");
                //改变信号灯   唤醒对方
                flag = true;
                this.notify();
            }
        }


        //南北 --> 车 -->true
        public void ns() {
            //false-->wait()
            if(flag != true) {
                try {
                    this.wait();  //当前线程进入到this对象的等待池中
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }else {   //车走
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("车走......");
                //改变信号灯   唤醒对方
                flag = false;
                this.notify();
            }
        }
    }


    class Person implements Runnable{
        //资源
        private Street street;

        public Person(Street street) {
            this.street = street;
        }

        @Override
        public void run() {
            while(true) {
                street.we();
            }

        }
    }


    class Car implements Runnable{
        //资源
        private Street street;

         public Car(Street street) {
             this.street = street;
        }

        @Override
        public void run() {
            while(true) {
                street.ns();
            }
        }
    }

网络编程

网络编程:

  1. 如何定位到一台电脑 IP(如人的身份证号码)
  2. 如何区分多个软件 (端口)
  3. 如何区分一个软件中的多个资源 url

IP位置

使用方法

    InetAddress.getLocalHost();返回本地主机的地址
    InetAddress.getByName("www.163.com");决定了IP地址的主机,主机的名字
    InetAddress.getByName("223.87.1.58");决定了IP地址的主机,主机的名字
    getHostAddress() 返回 ip 地址
    getHostName() 返回域名|本机为计算机名

示例:

    public class NetDemo01 {
        public static void main(String[] args) throws UnknownHostException {
            //static InetAddress getLocalHost() 返回本地主机的地址。  
            InetAddress i1 = InetAddress.getLocalHost();
            System.out.println(i1);   //DESKTOP-P04TCL5/192.168.14.111
            //static InetAddress getByName(String host) 决定了IP地址的主机,主机的名字。  
            InetAddress i2 = InetAddress.getByName("www.baidu.com");
            System.out.println(i2);  //www.baidu.com/180.101.49.12

            System.out.println(i1.getHostName());  //DESKTOP-P04TCL5
            System.out.println(i1.getHostAddress());  //192.168.14.111

        }
    }

端口(port)

端口是虚拟的概念,并不是说在主机上真的有若干个端口。通过端口,可以在一个主机上运行多个网络应用程序。

注意:

  • 同一个协议下端口号不能冲突

  • 8000以下的端口号不建议使用–>预留端口号

常见的端口号:

80 http

8080 tomcat

3306 mysql

1521 oracle

InetSocketAddress 端口类(ip+端口)

    //获取对象
    InetSocketAddress(String hostname, int port)
    InetSocketAddress(InetAddress addr, int port)

    //方法
    getAddress() 返回 InetAddress 对象
    getPort() 返回端口
    getHostName() 返回域名

示例:

public class PortDemo02 {
	public static void main(String[] args) {
		//InetSocketAddress(int port) 创建一个套接字地址的IP地址在哪里通配符地址和端口号一个指定的值。 
		InetSocketAddress in= new InetSocketAddress("localhost",8888);
		System.out.println(in);
		
		//ip
		System.out.println(in.getHostName());
		//端口号
		System.out.println(in.getPort());
	}
}

url

URL:统一资源定位符

互联网三大基石 : html http url

URL的语法表示形式为:

	协议://用户信息@主机名:端口/路径?查询#锚点

示例:

    public class URLDemo03 {
        public static void main(String[] args) throws MalformedURLException {
            //URL(String spec) 
            URL url = new URL("http://www.baidu.com:80/index.html?name=zhangsan&pwd=123#a");

            System.out.println(url);

            //getProtocol()  协议
            System.out.println("协议:"+url.getProtocol());
            System.out.println("域名:"+url.getHost());
            System.out.println("端口:"+url.getPort());
            System.out.println("资源:"+url.getFile());  //index.html?name=zhangsan&pwd=123
            System.out.println("文件:"+url.getPath());  
            System.out.println("数据:"+url.getQuery());  
            System.out.println("锚点:"+url.getRef());  

        }
    }

网络爬虫原理

简单爬虫

    package com.xxxx.net02;

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.MalformedURLException;
    import java.net.URL;

    /*
     * 	爬虫
     */
    public class SpiderDemo04{
        public static void main(String[] args) throws IOException {
            //1.URL
            URL url = new URL("http://www.baidu.com");
            //2.获取流(输入流)
            InputStream is = url.openStream();
            //通过InputStreamReader 把字节流转换成为字符流
            BufferedReader rd = new BufferedReader(new InputStreamReader(is));

            //3.读入
            String str=null;
            while((str=rd.readLine())!=null) {
                System.out.println(str);
            }

            //4.关闭
            rd.close();
            is.close();
        }
    }

协议

UDP协议

非面向连接 不安全 效率高 协议简单 开销小 大小有限一般不超过60k—>发送端和接受端两端平等 ---->字节数组

**UDP实现基本流程: 发送端 **

  1. 定义发送端 DatagramSocket(int port) 指定发送端ip和端口
  2. 准备数据–> 转为字节数组
  3. 打包 DatagramPacket(byte[] buf, int offset, int length, SocketAddress address) 构造一个数据报包发送数据包的长度 length抵消 ioffsetto指定主机上的指定端口号。
  4. 发送数据 send(DatagramPacket p) 从这个套接字发送一个数据报包。
  5. 关闭

示例:

    package com.xxxx.net03;

    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetSocketAddress;
    import java.net.SocketException;

    public class UDPSend01 {
        public static void main(String[] args) throws IOException {
            System.out.println("--------------我是发送端-----------------------------------");
            //1.定义发送端 DatagramSocket(int port) 指定发送端ip和端口
            DatagramSocket  send = new DatagramSocket(7777);
            //2.数据
            byte[] msg = "千年等一回".getBytes();
            //3.打包
            DatagramPacket  packet = new DatagramPacket(msg,0,msg.length,new InetSocketAddress("localhost", 8888));
            //4.发送
            send.send(packet);
            //5.关闭
            send.close();
        }
    }

UDP实现基本流程: 接收端

  1. 构建接收端
  2. 准备包裹–>用来接收数据
  3. 接收
  4. 处理数据
  5. 关闭

示例

package com.xxxx.net03;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class UDPReceive02 {
	public static void main(String[] args) throws IOException {
		System.out.println("--------------我是接收端-----------------------------------");
		//1.构建接收端
		DatagramSocket  receive = new DatagramSocket(8888);
		//2.准备包裹-->用来接收数据
		byte[] arr = new byte[1024*60];
		DatagramPacket  packet = new DatagramPacket(arr,arr.length);
		//3.接收
		receive.receive(packet);
		
		//4.处理数据
		/*
		 * byte[] getData() 
		          返回数据缓冲区。 
		   int getLength() 
		          返回将要发送或接收到的数据的长度。 
		 */
		byte[] result = packet.getData();
		int length = packet.getLength();
		System.out.println(new String(result,0,length));
		
		//5.关闭
		receive.close();
	}
}

TCP协议

面向连接 安全、可靠 效率低 基于IO流操作

Socket 套接字:

相当于传输层为应用层开辟的一个小口子

不同协议下Socket实现不同

面向Socket编程

TCP 基本流程: 客户端

  1. 创建客户端 Socket(String host, int port) 指定服务端的IP+端口
  2. 获取IO流
  3. 写出数据
  4. 关闭

示例:

package com.xxxx.net03;

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class TCPClient03 {
	public static void main(String[] args) throws UnknownHostException, IOException {
		System.out.println("---------------client--------------");
		//1.创建客户端
		Socket client =  new Socket("127.0.0.1",8888);
		//2.获取输入流
		OutputStream is = client.getOutputStream();
		//3.写出数据
		is.write("zhangsan".getBytes());
		//4.关闭
		is.close();
		client.close();
	}
}

TCP 基本流程: 服务端

  1. 创建服务端 ServerSocket(int port) 创建绑定到特定端口的服务器套接字。 服务端的端口号
  2. 阻塞式监听
  3. 获取IO流
  4. 读入数据
  5. 操作数据
  6. 关闭

示例:

package com.xxxx.net03;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPServer04 {
	public static void main(String[] args) throws IOException {
		System.out.println("---------------Server--------------");
		//1.创建服务端
		ServerSocket server = new ServerSocket(8888);
		//2.阻塞式监听
		Socket client = server.accept();
		System.out.println("-----------有一个客户端连接成功-------------------");
		
		//3.获取IO流  
		InputStream is = client.getInputStream();
		
		//4.读入数据
		byte[] car = new byte[1024];
		//把数据读入到字节数组car中,返回值len为读入到字节数组中真实数据的长度
		int len = is.read(car);
		
		//5.操作数据
		System.out.println(new String(car,0,len));
		
		//6.关闭
		is.close();
		client.close();
		server.close();
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值