JavaSE - 多线程与网络编程

多线程

一、目前存在的问题

程序同一时间只能做一件事

二(??)

创建多线程的方法
  1. 继承Thread类

  2. 实现Runnable接口

  3. 实现Callable接口

  4. 线程池创建

三、继承Thread类创建线程

  1. 自定义线程类继承Thread类

  2. 重写run方法 -- run方法中的内容就是线程体

  3. 创建自定义线程类的对象

  4. 调用start方法启动线程

 public class ChatThread extends Thread{
     @Override
     public void run() {
         for(int i = 0;i < 100; i++){
             System.out.println("聊天");
             try {
                 Thread.sleep(100);
             } catch (InterruptedException e) {
                 throw new RuntimeException(e);
             }
         }
     }
 }
 ​
 public class EatThread extends Thread {
     @Override
     public void run() {
         for(int i = 0;i < 100; i++){
             System.out.println("吃饭");
             try {
                 Thread.sleep(100);
             } catch (InterruptedException e) {
                 throw new RuntimeException(e);
             }
         }
     }
 }
 ​
 public class DrinkThread extends Thread{
     @Override
     public void run() {
         for(int i = 0;i < 100; i++){
             System.out.println("喝酒");
             try {
                 Thread.sleep(100);
             } catch (InterruptedException e) {
                 throw new RuntimeException(e);
             }
         }
     }
 }
 ​
 public static void main(String[] args) {
     //创建线程类的对象
     DrinkThread drinkThread = new DrinkThread();
     ChatThread chatThread = new ChatThread();
     EatThread eatThread = new EatThread();
     //启动线程
     drinkThread.start();
     chatThread.start();
     eatThread.start();
 }

ps.

  1. 启动线程用start(),不能用run()

start()只能调用一次

  1. run()start()的区别?

  • start():用来启动线程,通过该线程调用run方法执行run方法中所定义的逻辑代码。start方法只能被调用一次。

  • run():封装了要被线程执行的代码,可以被调用多次。

四、runnable

步骤:

  1. 自定义线程类,实现runnable接口

  2. 在自定义类中,实现run方法

  3. 创建自定义类对象并将该对象传入Thread类的构造方法中得到Thread类的对象

  4. 调用Thread类的start方法启动线程

优势:

  • 避免了单继承的局限性;

  • 多个线程可以共享同一个接口实现类的对象,非常适合多个相同线程来处理同一份资源

 MyThread t1 = new MyThread();
 MyThread t2 = new MyThread();
 ​
 t1.setName("线程1");
 t2.setName("线程2");
 ​
 t1.start();
 t2.start();
 ​
 for(int i = 1; i <= 100; i++){
     System.out.println(Thread.currentThread().getName() + ":" + i);
 }//currentThread --获取当前线程的引用
 //getName() -- 获取当前线程的名字
 //setName() -- 为线程设置名字

 Thread th1 = new Thread(new Runnable() {
     @Override
     public void run() {
         System.out.println("t1");
     }
 });
 ​
 Thread th2 = new Thread(new Runnable() {
     @Override
     public void run() {
         try {
             th1.join();
         } catch (InterruptedException e) {
             throw new RuntimeException(e);
         }
         System.out.println("t2");
     }
 });
 ​
 Thread th3 = new Thread(new Runnable() {
     @Override
     public void run() {
         try {
             th2.join();
         } catch (InterruptedException e) {
             throw new RuntimeException(e);
         }
         System.out.println("t3");
     }
 });
 ​
 th3.start();
 th2.start();
 th1.start();

 public class MyThread extends Thread {
     private Thread t;
 ​
     public MyThread(Thread t){
         this.t = t;
     }
 ​
     public void run(){
         try {
             if (t != null) {
                 t.join();
             }
         } catch (InterruptedException e) {
             throw new RuntimeException(e);
         }
      System.out.println(Thread.currentThread().getName());
     }
 }
 ​
 ​
 public class MyTest1 {
     public static void main(String[] args) {
         Thread t1 = new MyThread(null);
         Thread t2 = new MyThread(t1);
         MyThread t3 = new MyThread(t2);
 ​
         t1.setName("线程1");
         t2.setName("线程2");
         t3.setName("线程3");
 ​
         t3.start();
         t1.start();
         t2.start();
     }
 }

 public class MyTest1 {
     public static void main(String[] args) {
         Window w = new Window();
 ​
         Thread w1 = new Thread(w);
         Thread w2 = new Thread(w);
         Thread w3 = new Thread(w);
 ​
         w1.setName("窗口1");
         w2.setName("窗口2");
         w3.setName("窗口3");
 ​
         w1.start();
         w2.start();
         w3.start();
     }
 }
 ​
 public class Window implements Runnable{
     private Integer no = 100;
     
     @Override
     public void run() {
         while(true){
             synchronized (no){
                 if(no <= 0){
                     break;
                 }
                 System.out.println(Thread.currentThread().getName() + "销售第" + no + "张票");
                 no--;
             }
 ​
             try {
                 Thread.sleep(10);
             } catch (InterruptedException e) {
                 throw new RuntimeException(e);
             }
         }
     }
 }

 public class MyTest2 {
     private static SingleObject obj1;
     private static SingleObject obj2;
 ​
     public static void main(String[] args) throws InterruptedException{
         Thread t1 = new Thread(new Runnable() {
             @Override
             public void run() {
                 obj1 = SingleObject.getObject();
             }
         });
         Thread t2 = new Thread(new Runnable() {
             @Override
             public void run() {
                 obj2 = SingleObject.getObject();
             }
         });
 ​
         t1.start();
         t2.start();
 ​
         Thread.sleep(1000);
         System.out.println(obj1 == obj2);
     }
 }
 //一会true一会false的?????????????????????????????

五、Thread类方法

  • start():启动线程,并执行对象的run()方法;

  • run():线程在被调用时执行的操作;

  • getName():返回线程的名称;

  • setName():设置线程的名称;

  • currentThread():返回当前线程。

六、线程的调度和生命周期

  1. 调度策略:

  • 基于时间片轮转

  • 抢占式

  1. 生命周期:

  • 新建(NEW)

  • 可运行(RUNNABLE)

  • 终结(TERMINATED)

  • 阻塞(BLOCKED)

  • 等待(WAITING)

  • 有时限等待(TIMED_WAITING)

七、死锁

  1. 死锁:不同的线程分别占用对方需要的同步资源

网络编程

网络编程

1. 目的

直接或间接地通过网络协议与其他计算机进行通讯

2.需要解决的问题
  • 如何准确地定位网络上一台或多台主机:IP

  • 如何定位主机上的特定应用:端口

  • 找到主机后如何可靠高效地进行数据传输"协议

3.网络通信
  1. 设备和设备

  2. 进程和进程

    1)不同设备之间

    2)本地设备之间

网络协议

1.OSI

应用层,表示层,会话层,传输层,网络层,数据链路层,物理层

2.TCP\IP
  • 以TCP和IP为主的一系列应用层协议

应用层, 传输层,网络层, 数据链路层

3.TCP和UDP

IP地址和端口号

1.ip地址

唯一的标识Internet上的计算机(通信实体)。

2.本地回环地址

127.0.0.1

3.ip地址分类方式

1)

  • IPV4:4个字节组成,4个0-255。以点分十进制表示,如192.168.0.1

  • IPV6:128位(16个字节),写成8个无符号整数,每个整数用四个十六进制位表示, 数之间用冒号:分开,如:3ffe:3201:1401:1280:c8ff:fe4d:db39:198

2)

  • 公网地址(万维网使用)

  • 私有地址(局域网使用)

4.端口号

1)标识进程,不同进程有不同的端口号,是一个16位的整数

2)分类

  • 公认端口:0~1023

  • 注册端口

  • 动态/私有端口

3)端口号与IP地址的组合得出一个网络套接字Socket

5.InetAddress类

1)Internet上的主机有两种方式表示地址:

  • 域名(stage1.codeaction.org)

  • IP地址

2)InetAddress主要作用是表示IP地址,有两个子类:

  • Inet4Address

  • Inet6Address

3)InetAddress类对象含有一个Internet主机地址的域名和IP地址:

  • stage1.codeaction.org

  • 216.127.178.187

4)域名解析过程:

  • 先找本机hosts文件,是否有输入的域名地址;

  • 没有的话,再通过DNS服务器,找主机。

5)静态方法获取InetAddress

  • public static InetAddress getLocalHost()

  • public static InetAddress getByName(String host)

6)常用方法

  • public String getHostAddress():返回IP地址字符串(以文本表现形式)

  • public String getHostName():获取此IP地址的主机名

  • public boolean isReachable(int timeout):测试是否可以达到该地址

6.Socket

通信的两端(客户端、服务端)都要有Socket,是两台机器间通信的端点。

网络通信其实就是Socket间的通信。

1)Socket分类

  • 流套接字:使用TCP提供可依赖的字节流服务

  • 数据报套接字:使用UDP提供尽力而为的数据报服务。

2)常用构造器

  • public Socket(InetAddress address, int port)创建一个流套接字并将其连接到指定IP地址的指定端口号;

  • public Socket(String host, int port)创建一个流套接字并将其连接到指定主机上的指定端口号。

3)常用方法

  • getLocalAddress():返回本地Socket中的IPInetAddress对象;

  • getLocalPort():返回本地Socket中的端口号;

  • getInetAddress():返回对方SocketIP地址;

  • getPort():返回对方Socket中的端口号;

  • close():关闭套接字;

  • getInputStream():获取输入流,用来读取数据;

  • getOutputStream():获取输出流,用来发送数据。

基于TCP/IP的服务器和客户端

作用:1.客户端能够连接服务器

  1. 客户端能够给服务器

 //服务器
 public class Server{
     main{
         //创建监听套接字
         ServerSocket st = new ServerSocket(60000);
         while(true){
             //创建连接套接字 - 表示有客户端连接
             Socket socket = st.accept();
             int len = 0;
             //IO操作
             InputStream in = socket.getInputStream();
             while(true){
                 len = in.read(arr,0,arr.length);
                 if(len == -1){
                     break;
                 }
                 String s = new String(arr,0,len);
                 sout(s);
             }
             //关闭套接字
             socket.close();
         }
     }
 }
  • 10
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值