A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 小石姐姐 于 2018-4-25 17:00 编辑

多线程

进程 : 是一个应用程序在内存中的执行区域,比如一个正在运行的程序,可以有一个或者多个进程
一个正在运行的程序,可以有一个或多个进程,每个进程都会占用一部分的系统资源,如CPU,内存,磁盘,网络等
而线程则是一个进程中的一个执行路径 如:
一个进程中可以有一个或多个线程
每个线程可以执行自己的代码
多个线程各自执行的任务可以同时进行
线程的执行依靠CPU调度分配
单核CPU: 靠CPU不断高速的随机的切换执行的线程, 达到看似同时进行的效果
多核CPU: 每个CPU可能完全执行一个线程, 或者多个CPU各自不断高速随机切换, 更高效
单线程: 同一时间只做一件事情, 安全性高, 效率低.
多线程: 同一时间做多件事, 安全性低, 效率高.
什么是并发?        并发就是并行发生, 同时发生, 多线程就可以实现并发
同步: sync, 同步是指一步接一步的执行, 一个执行完毕再开始执行下一个.
异步: async,同时执行多步, 每个步骤何时结束不确定.
阻塞: 上一行代码正在执行, 还没有执行完毕, 程序就阻塞了, 下一行代码必须等上一行不再阻塞后才能执行
创建线程的第一种方式: 继承Thread类
Thread Thread(): 创建Thead对象
Thread Thread(Runnable r)`: 通过Runnable对象创建Thread对象
Thread Thread(Runnable r, String threadName): 通过Runnable对象创建Thread对象并指定线程名
成员方法
void run()`: 用于让子类重写, 表示该线程要执行的任务. 不能直接调用
void start(): 启动线程, 即让线程开始执行run()`方法中的代码
String getName()`: 获取线程的名称
void setName(String name)`: 设置线程名称
静态方法
static Thread currentThread()`: 返回对当前正在执行的线程对象的引用
static void sleep(long millis)`: 让所在线程睡眠指定的毫秒
多线程实现方式1:
定义类, 继承Thread类, 重写run()方法
步骤:
  • 定义一个类, 继承Thread类
  • 在子类中重写父类的run()方法
  • 创建子类的对象
  • 调用子类对象的start()方法启动线程


main()方法也是执行在一个线程中的,是单线程的, 方法中的代码是一行一行向下执行的
创建线程的第二种方式:实现Runnable接口
实现Runnable接口, 重写run()方法
步骤
  • 定义一个类, 实现Runnable接口
  • 在子类中重写父类的run()方法
  • 创建一个子类的对象
  • 创建Thread对象, 在其构造方法中传入刚才创建的子类的对象
  • 调用Thread对象的start()方法启动一个线程


多线程中的线程安全问题: 使用同步代码块去解决共享资源问题
同步:多个线程在执行同步的代码时,程序只能按照顺序一个一个去执行
优点:同步安全性高,效率低
同步代码块: 使用synchronized修饰的代码块
作用:
被同步代码块包裹的代码相当于在一个房间内, 锁对象相当于房间的锁
一个线程进入同步代码块, 会把门锁上, 同步代码块外面的线程看到同步代码块内部有线程, 只能在外面等待
直到同步代码块内部的线程执行完毕从代码块中出来, 释放了锁, 外面等待的线程才能随机进去一个
应用位置:
哪些代码属于共享操作, 需要避免安全问题, 就将这些代码放入同步代码块
术语
线程进入同步代码块, 叫获取锁
线程出同步代码块, 叫释放锁
锁是一个任意类型的对象,必须是被所有线程共享的,同步代码块必须配合所对象来使用
出现多线程的安全问题, 检查一下2个方面
  • 对于操作了了共享数据的代码是否是同步的?
  • 同步使用的是否是同一个锁对象?


继承Thread 类和实现Runnable接口在共享资源上有啥区别?
继承Thread类: Thread类中的非静态变量成员变量是每个线程各自拥有的,不能作为共享资源
静态成员变量是所有线程对象共享的,可以作为共享资源
实现Runnable接口: 如果所有的Thread对象都传入同一个Runnable对象,那么
Runnable对象中的非静态成员变量会被所有线程共享,可以作为共享资源
Runnable对象中的静态成员变量也会被所有Thread对象共享,也可以作为共享资源
  所以, 继承Thread类方式下,共享资源要定义成Thread类的静态资源
实现Runnable接口方式下,共享资源要定义为Runnable接口的静态或非静态资源,并且所有Thread对象都要传入同一个Runnable对象
线程的生命周期
线程的生命周期中有5种状态
  • 创建: new一个线程对象, 此时还没有调用start()
  • 就绪: 调用start()方法后, 进入就绪状态, 等待CPU执行
  • 运行: 获取了CPU的执行权, 开始运行线程
  • 阻塞: 调用了sleep(), wait(), 或由于IO操作导致阻塞. 阻塞解除后仍会返回就绪状态, 等待CPU执行
  • 销毁: 线程执行完毕


线程之间的通信
wait():使当前此案成处于等待状态,并且会立刻释放锁
notify():随机唤醒一个处于等待状态的线程
notifyAll(): 唤醒全部处于等待状态的线程
注意:这三个方法必须在同步代码块中,且只能用锁对象来调用,否则会抛异常
sleep()和wait()有啥区别?
sleep() : 让当前的线程在指定的时间睡眠, 时间结束后就继续执行.不会释放锁
wait(): 让当前线程等着,知道有人唤醒,会立刻释放锁
线程释放锁的3种情况
  • synchronized同步代码执行完毕
  • 线程发生了异常导致线程终止
  • 线程调用了wait()方法进行等待, 等待会立刻释放锁


死锁??????
死锁: dead lock
同步代码块中的线程不出来, 也不释放锁; 同步代码块外的线程拿不到锁, 只能等在外面.
发生死锁的原因:
  • 同步代码块内的线程, 可能处在死循环, IO阻塞, sleep()状态, 导致内部持有锁的线程无法出同步代码块
  • 多个线程互相持有锁又不释放锁: 两个线程执行的任务都是双层同步代码块, 每层同步都需要一个锁, 两个线程中同步代码块的锁是相反的


死锁的结果: 程序卡死, 无法继续执行
怎么避免死锁:
避免在同步代码块中执行死循环, IO阻塞操作, sleep()
避免多个线程互相持有锁又不释放锁的情况
另一种加锁方式: Lock类
// 创建锁对象, 该锁对象也要所有线程共享唯一一个private Lock lock = new ReentrantLock();
lock.lock();    // 加锁, 相当于执行到synchronized// 同步的代码lock.unlock();  // 释放锁, 相当于同步代码块执行完毕网络
day12网络网络编程概述
网络编程:
Socket :  中文译名为        套接字      对协议的一个封装
用于描述IP地址和端口,时一种网络编程机制,通信两端都有Socket
网络通信三要素
传输协议:  通信的规则
​                作用:通信的规则
​                常见协议:  
TCP// 传输控制协议 :
​        需要建立链接的可靠协议
​        没有数据传输大小的概念
​        在传输前需要先建立连接(三次握手)
​        重发机制, 如果接收方没有接收到信息,发回验证信息,然后发送方会重新发送
​        所以数据发送时间长,数据流量大
使用场景: 适合准确性要求强的场合,比如金融系统,视频点播(可缓冲)
形成传输数据的通道,通过三次握手完成链接,可靠协议,效率低
UDP// 用户数据报协议:
         无连接的不可靠的协议
​        数据传输大小限制为64K(一个包)
​        不需要建立连接随便扔
​        数据发送速度快,发送方只管发送数据,不管你接没接到,所以可能又丢包情况
使用场景:
​        适合实时性要求强的场合,QQ语音,微信视频,卡掉就是卡掉了,中间空白了
​        
IP地址 : 是一个二进制数字    如www.badu.com 会通过DNS 查询IP地址
​        IP 可以使用主机名或域名代替,更容易记忆
端口号:
​        作用: 标识使用网络通信的进程的逻辑地址,用于定位一个主机上的具体服务
​        端口号范围: 0 - 65535   前1024个端口时系统保留的端口号
​        常见服务占用的端口
80: HTTP服务
443: HTTPS服务,安全加密的HTTP
21: FTP服务,文件传输
22: SSH服务,安全加密的远程登陆
23: Telnet服务,远程登陆
举例理解三要素(寄快递)
         传输协议:用什么快递
​        IP地址: XX省XX市XX街道XX号
​         端口号: X楼
InetAddress概述和测试
java.net.包下InetAddress类: 用于表示IP地址对象(包含IP地址和主机名)
static InetAddress getLocalHost() :获取本机的InetAddress对象
getByName():根据主机名IP的字符串获取主机对象
getLoopbackAddress(): 获取回环地址的InetAddress的对象,
static InetAddress getByAddress(byte[] addr): 根据IP获取InetAddress对象
getHostName(): 获取主机名
getHostAddress(): 获取IP地址
getLocalHost(): 获取本机主机名
ipconfig:  在cmd中输入用于查看本机的IP信息UDP协议发送数据
  • 创建发送端Socket对象
  • 创建数据并打包  // 数据:字节数组  byte[] ,设备的地址IP,端口号
  • 发送数据
  • 释放资源


DatagramSocket : 基于UDP协议的Socket
​        构造方法:
​        DatagramSocket(): 创建Socket对象并随机分配端口号
​        DatagramSocket(int port) : 创建Socket对象并指定端口号
​        成员方法:
​        send(DatagramPacket p): 发送数据包
​        receive(DatagramPacket p ): 接收数据,数据保证在DatagramPacket对象中
​        close(): 关闭通信,释放资源
DatagramPacket 类: UDP数据包
构造方法:
DatagramPacket(byte[] msg, int msgLength, InetAddress host, int port): 创建数据包对象, 指定数据, 目标主机对象, 端口
DatagramPacket(byte[] buf,int length):创建数据包对象,接收数据为length的数据,存入byte数组中
成员方法
  • InetAddress getAddress(): 获取数据包发送方的InetAddress对象        
  • byte[] getData(): 获取包中的数据, 以byte数组形式
  • int getLength(): 获取数据的长度, 即byte数组的长度
  • int getPort(): 获取发送方端口号


UDP协议接收数据
端口号错误,数据可以正常发出,不会出现异常,但是收不到数据
BindException : 端口绑定异常  端口号不能重复,
TCP协议发送数据
构造方法: Socket(InetAddress add, int port): 创建TCP客户端对象
成员方法:
  • OutputStream getOutputStream(): 获取输出流对象, 用于发送数据
  • InputStream getInputStream(): 获取输入流, 用于接收数据
  • void close(): 释放资源
    TCP发送数据步骤
  • // 1. 创建客户端Socket对象(建立连接)Socket socket = new Socket(InetAddress地址, 端口号);// 2. 获取输出流对象OutputStream outputStream = socket.getOutputStream();// 3. 发送数据outputStream.write(byte数组);// 4. 释放资源socket.close();TCP协议接收数据
    java.net.ServerSocket`: TCP服务端

    • 构造方法

      • ServerSocket(int port): 创建一个TCP服务端, 并监听指定端口


    • 成员方法

      • Socket accept(): 监听数据, 会阻塞. 收到数据后返回Socket对象
      • void close(): 关闭Socket
        反射Reflect
      • 反射:Reflect
        在运行时,我们可以获取任意一个类的所有方法和属性(包括私有的)
        在运行时,让我们调用任意一个对象的所有方法和属性(包括私有的)
        反射的前提:
        要获取类的对象(Class对象)
        获取字节码对象的三种方式 //建立了一个student类

        • 通过Object的getClass()方法获取,必须有对象
          student s = new student();
          Class clazz = s.getClass;
        • 通过类名获取字节码对象
          Class clazz = Student.class;
        • static Class<?> forName(String className)
          Class clazz = Class.forName(" 全部的类名")
          反射获取构造方法并创建对象反射使用的相关类和方法
          java.lang.Class类: 类的字节码对象
          获取构造方法:
          Constructor<?>[ ] getConstructors(): 以数组形式返回该类中的所有public的构造方法,如果没有public的,则数组长度长度为0
          Constructor<?>[ ] getDeclaredConstructors(): 以数组形式返回该类中所有权限的构造方法,包括私有的,如果该类时接口,基本类型,数组,void,则数组长度为0
          Constructor<?>[ ] getConstructors(Class<?>... parameterTypes): 根据参数列表返回指定的public的构造方法,参数列表填写参数的字节码对象
          Constructor<?>[ ] getDeclaredConstructors(Class<?>... parameterTypes):根据参数列表返回指定的所有权限的构造方法,包括私有的,参数列表填写参数的字节码对象


        创建对象:
        T newInstance()
        反射获取public成员变量:设置和获取值成员变量方法:
        getFields(): 获取公共的成员变量
        getFields(): 获取所有public的成员变量
        getDeclaredFields(): 获取所有权限的成员变量.包括私有的
        getFields(String fieldName):  通过指定的成员变量名获取指定的punlic成员变量
        getDeclaredFields(String fieldName): 通过指定的成员变量名获取指定的所有权限的成员变量.包括私有的
        成员变量对象:
        Object get(Object obj): 获取指定对象的属性值,传入对象,返回该对象的属性
        反射获取成员方法并调用
        获取成员方法:
        Method [ ]  getMethods(): 返回所有public的方法数组
        Method [ ]  getDeclaredMethods(): 返回所有权限的方法数组
        Method  getMethods(String name,Class<?>... parameterTypes): 获取public的方法,传入方法名和方法形参字节码对象


      • HTML :超文本标记语言
        扩展名为.html 或者.htm
        空格:&npsp
        <hr/ > 横线
        <pre>:原生标签,把copy过来的内容原封不动的粘过来
        字体标签
        <font>文字</font>
        <font>标签的属性:
        color:字体的颜色
        size:字体的大小
        face: 字体
        标题标签<h1>...<h6>
        段落标签<p>
        粗体标签<b>
        斜体标签<i>
        下划线标签<u>
        居中显示<center>
        图片标签<img>
        属性:
        src: 图片的来源路径
        width: 图片的宽度
        height: 图片的高度
        alt:图片找不到显示的内容
        图片引入的路径问题?
        路径:相对路径
        同一路径可以直接写文件名或 ./ 文件名
        上一级目录: ../
        列表标签
        有序列表<ol>
        <li></li>
        </ol>
        type属性 :
        1    数字类型
        a     英文类型
        i      罗马字符
        start : 从哪里开始,
        无序列表<ul>
        <li></li>
        </ul>
        type属性:
        disc :实心点
        circle:空心圆
        square:方块
        超链接标签
        <a>
        属性:
        href:  链接的路径
        target: 打开的方式
        _self : 在自身页面打开
        _blank : 新打开一个窗口
        _parent :
        表格标签
        <table>
        <tr> :行
        <td> :列
        属性:
        width: 表格宽度
        height:表格高度
        border: 边框
        aligh: 表格水平位置:
        ​        left :居左
        ​        right: 居右
        ​        center:居中
        <td>的属性:
        合并表格:
        colspan = "列数"
        rowspan = "行数"
        HTML的表单标签<from>常用属性:
        action属性: 提交的路径,如果没指定默认提交到当前页面
        method属性: 请求的方式,GET和POST,默认是GET
          常问的面试题:GET和POST属性的区别?
        GET: 数据会显示到地址看重 , 提交是有大小限制的,请求行里边
        POST: 数据不会显示到地址栏中 . 相对来说安全一点,提交没有大小限制,请求体中
        <input type = "text">        :文本框
        ​                name  :  表单名称,要有名字方便后台接收
        ​                value  : 文本框的默认值
        ​                size : 设置文本框的长度
        ​                maxlength : 设定几个数字  就只能接收几个数字
        ​                readonly :  不允许输入的.只读的
        <input type = "password">        :密码框
        ​                name  :  表单名称,要有名字方便后台接收
        ​                value  : 文本框的默认值
        ​                size : 设置文本框的长度
        ​                maxlength : 设定几个数字  就只能接收几个数字
        <input type = "radio">                :单选按钮
        ​                name  :  表单名称,要有名字方便后台接收
        ​                value  :单选按钮的默认值
        ​                checked : 单选按钮默认被选中
        <input type ="checkbox">        :复选框
        ​                name  :  表单名称,要有名字方便后台接收
        ​                value  :单选按钮的默认值
        ​                checked : 单选按钮默认被选中
        <input type ="button">        :普通按钮<input type ="submit">        :提交按钮<input type ="reset">        :重置按钮<input type ="file">        :文件上传(可浏览上传)<input type ="hidden">        :隐藏字段<input type ="image">        :图片按钮<select>        : 下拉列表<textarea>        : 文本域HTML5扩展的表单标签(不是所有浏览器都支持)
        <input type = "email">        :只能输入邮箱形式的
        <input type = "date">                :只能输入日期形式的
        <input type = "number">        :只能输入数字
        <input type = "color">                :颜色板  可以直接选
        ​               
        此致......








0 个回复

您需要登录后才可以回帖 登录 | 加入黑马