• 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

  • 相关阅读:
    微服务架构技术栈选型手册(万字长文)
    Visual Studio 2013 always switches source control plugin to Git and disconnect TFS
    Visual Studio 2013 always switches source control plugin to Git and disconnect TFS
    MFC对话框中使用CHtmlEditCtrl
    ATL开发 ActiveX控件的 inf文件模板
    ActiveX: 如何用.inf和.ocx文件生成cab文件
    Xslt 1.0中使用Array
    如何分隔两个base64字符串?
    An attempt was made to load a program with an incorrect format
    JQuery 公网 CDN
  • 原文地址:https://www.cnblogs.com/hunter-w/p/13929559.html
Copyright © 2020-2023  润新知