zoukankan      html  css  js  c++  java
  • Java多线程

    多进程和多线程简介

    • 多进程概念

      当前的操作系统都是多任务OS

      每个独立执行的任务就是一个进程

    • 多进程的优点

      1. 可以同时运行多个任务
      2. 程序因IO堵塞时,可以释放CPU,让CPU为其他程序服务
      3. 当系统有多个CPU时,可以为多个程序同时服务
    • 多进程的缺点

      1. 太笨重,不好管理
      2. 太笨重,不好切换
    • 多线程概念

      一个程序可以包括多个子任务,可串/并行

      每个子任务可以称为一个线程

      如果一个子任务阻塞,程序可以将CPU调度另外一个子任务进行工作。这样CPU还是保留着本程序中,而不是被调度到别的程序(进程)中,提高本程序所获得CPU时间和利用率。

    • 多进程和多线程对比

      1. 线程共享数据
      2. 线程通讯更高效
      3. 线程更轻量级,更容易切换
      4. 多个线程更容易管理

    Java多线程创建

    • java.lang.Thread

      • 线程继承Thread类,实现run方法

        public class Thread1 extends Thread {
        	public void run()
        	{
        		System.out.println("hello");
        	}
        }
        
    • java.lang,.Runnable接口

      • 线程实现Runnable接口,实现run方法

        public class Thread2 implements Runnable {
        	public void run()
        	{
        		System.out.println("hello");
        	}
        }
        
        /* 启动方法 */
        new Thread(new Thread2()).start();
        
      • Java的四个主要接口:

        Clonable,用于对象克隆
        
        Comparable,用于对象比较
        
        Serializable,用于对象序列化
        
        Runnable,用于对象线程化
        
    • 启动

      • start方法,会自动以新进程调用run方法
      • 直接调用run方法,将变成串行执行
      • 同一个线程,多次start会报错,只执行第一次start方法
      • 多个线程启动,其启动的先后顺序是随机的
      • 线程无需关闭,只要其run方法执行结束后,自动关闭
      • main函数(线程)可能早于新线程结束,整个程序并不终止
      • 整个程序终止是等所有的线程都终止(包括main函数线程)
    • Thread vs Runnable

      • Thread占据了父类的名额,不如Runnable方便

      • Thread类实现Runnable

      • Runnable启动时需要Thread类的支持

      • Runnable更容易实现多线程中资源共享(Thread里必须用static变量,才能实现变量共享,Runnable通过普通变量便可达到)

        一个线程只能启动一次,通过Thread实现线程时,线程和线程所要执行的任务是捆绑在一起的。也就使得一个任务只能启动一个线程,不同的线程执行的任务是不相同的,所以没有必要,也不能让两个线程共享彼此任务中的资源。

        一个任务可以启动多个线程,通过Runnable方式实现的线程,实际是开辟一个线程,将任务传递进去,由此线程执行。可以实例化多个 Thread对象,将同一任务传递进去,也就是一个任务可以启动多个线程来执行它。这些线程执行的是同一个任务,所以他们的资源是共享。

      • 结论:建议实现Runnable接口来完成多线程

    Java多线程信息共享

    • 线程类

      • 通过继承Thread类或实现Runnable
      • 通过start方法,调用run方法,run方法工作
      • 线程run结束后,线程退出
    • 粗粒度:子线程与子线程之间、和main线程之间缺乏交流

    • 细粒度:线程之间有信息交流通讯

      • 通过共享变量达到信息共享
      • JDK原生库暂不支持发送消息(类似MPI并行库(C++)直接发送消息)
    • 通过共享变量在多个线程中共享消息

      • static变量
      • 同一个Runnable类的成员变量
    • 多线程信息共享问题

      • 工作缓存副本
      • 关键步骤缺乏加锁限制
    • i++,并非原子性操作

      • 读取主存i(正本)到工作缓存(副本)中
      • 每个CPU执行(副本)i+1操作
      • CPU将结果写入到缓存(副本)中
      • 数据从工作缓存(副本)刷到主存(正本)中

    • 变量副本问题的解决方法

      • 采用volatile关键字修饰变量

        用volatile修饰的变量可以及时在各线程里面通知

      • 保证不同线程对共享变量操作时的可见性

    • 关键步骤加锁限制

      • 互斥:某一个线程运行一个代码段(关键区),其他线程不能同时运行这个代码段
      • 同步:多个线程的运行,必须按照某一种规定的先后顺序来运行
      • 互斥是同步的一种特例
    • 互斥的关键字是synchronized

      • synchronized代码块/函数,只能一个线程进入
      • synchronized加大性能负担,但是使用简便

    Java多线程管理

    • 线程状态

      • NEW刚创建
      • RUNNABLE就绪态(start)
      • RUNNING运行中(run)
      • BLOCK阻塞(sleep)
      • TERMINATED结束
    • Thread的部分API已经废弃

      • 暂停和恢复suspend/resume
      • 消亡stop/destroy
    • 线程阻塞/和唤醒

      • sleep,时间一到,自己会醒来
      • wait/notify/notifyAll,等待,需要别人来唤醒
      • join,等待另一个线程结束
      • interrupt,向另外一个线程发送中断信号,该线程收到信号,会出发InterruptedException(可解除阻塞),并进行下一步处理
    • 线程被动地暂停和终止

      • 依靠别的线程来拯救自己
      • 没有及时释放资源
    • 线程主动暂停和终止

      • 定期监测共享变量
      • 如果需要暂停或终止,先释放资源,再主动动作
      • 暂停:Thread.sleep(),休眠
      • 终止:run方法结束,线程终止
    • 多线程死锁

      • 每个线程互相持有别人需要的锁
      • 预防死锁,对资源进行等级排序
    • 守护(后台)线程

      • 普通线程的结束,是run方法运行结束
      • 守护线程的结束,是run方法运行结束,或main函数结束
      • 守护线程永远不要访问资源,如文件或数据库
    • 线程查看工具:jvisualvm

  • 相关阅读:
    首页效果
    vue 资源精选
    webpack
    常用代码
    超炫效果
    TJ 大神 与 node
    fis webpack 原理对比
    前端自动化测试
    非常强的用户体验的网站功能
    蔡康永: 说话之道
  • 原文地址:https://www.cnblogs.com/hunter-w/p/13929559.html
Copyright © 2011-2022 走看看