多线程学习笔记(基础篇)

Java多线程_基础

进程和线程

  • 进程:
    操作系统中一个程序的运行周期叫做一个独立的进程 是操作系统元调度的最小单位 每个进程都拥有一套独立的变量
  • 线程:
    线程是进程的一个任务
    线程之间共享变量
    每个线程的内部都有自己的一套变量,每个线程内的变量是私有的(工作内存)(java内存模型)

线程的状态和一些常用方法

  • 线程有以下五种状态:
    开始、就绪、运行、阻塞 、终止

  • start(): 线程启动
    调用这个方法,线程变为就绪态,但是什么时候调用时操作系统决定的
    start()方法实际上内部是调用了start0()的本地方法,目的是先进行资源的调度来实现多线程

  • sleep(long time):
    线程休眠 ,线程立刻交出CPU给其他线程执行任务,但是不交出锁,等到指定的时间在回复执行,
    线程的状态从运行态到阻塞态。
    TimeUnit.SECONDS.SLEEP()

  • yield()
    线程让步,线程交出CPU给其他线程执行任务,但是不立刻交出要等到当前任务完成才会交出
    yield()方法只会让有相同优先级的线程有可能获取到CPU
    线程从运行态到就绪态,什么时候回到运行态是系统决定的

  • join()
    等待线程执行完毕,会阻塞其他线程直到此线程执行完毕
    在哪个线程执行该方法就会让哪个线程阻塞
    实际上是wait()方法的包装方法

  • currentThread()
    获取当前线程

  • getName()
    获取线程名称

  • interrupt()
    线程中断
    不会立刻终止正在运行中的线程,而是等待其运行完毕后才会进行终止
    实质:
    1.实际上是设置了一个标志位,每当调用interrupt类时,会将标志位改为true
    2.如果一个正在阻塞状态的线程(wait(),join(),sleep()),调用了此方法,会立刻终止线程,然后抛出一个InterruptedException(),并将标志位改为false
    3.如果先调用iterrupted()方法再,进行阻塞,不会立刻终止线程,等到线程执行完毕后才会抛出InterruptedException()
    run()方法是线程实现的实体方法

  • 线程优先级
    线程优先级是优先级高的线程会有可能优先被执行
    可以自己设置优先级 方法 setPriority()
    优先级是从1到10 主线程的优先级是5

  • 守护线程:
    是一种守护机制,只要程序中还有工作线程没有结束,守护线程就不会终止,只有最后一个工作线程结束,守护线程才会结束
    Java中的守护线程有 垃圾回收线程

  • 如何创建多线程
    1)通过继承Thread类来实现多线程
    2)通过继承Runnable类来实现多线程
    实际上,还是需要通过 Thread类中的start()方法来回调Thread类中的run()方法
    相当于一种代理模式,核心业务类为自己定义的实现Runnable的类,将类实例化对象传入Thread类里面,来进行多线程的实现
    可以使用匿名内部类或者lamda表达式(new Thread(new Runnable{} 或者 new Thread(()->()));
    3)通过继承Callable类来实现多线程,和Runnable一样,不过Callable类支持返回提示信息
    具体实现
    1.Callable不是Thread类的父接口,
    2.Callable的返回值是通过一个接口口Future接口的get()方法来获得的
    3.Future接口有一个具体子类FutureTask里面有成员变量Callable,
    4.FutureTask即是Future的子类又是Runnable的子类,所以可以通过这个类来将核心业务传入Thread类中,来执行多线程的
    注意:
    Future类保证任务只执行一次,所以看不到多线程,如果想看到多线程就要使用线程池使用submit(Runnable或者Callable)来提交任务
    get方法会阻塞当前线程,直到有返回值才会继续向下执行

  • 通过线程池来创建多线程

  • 什么是线程池
    线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。

  • 线程池创建多线程的好处是什么
    1.提高响应速度:每当有一个任务到达,无序创建新线程就可以直接执行
    2.减少资源浪费:恢复用已有的线程
    3.方便线程的统一管理:对线程进行统一的资源分配调度

  • 线程池的几个组成

  • 核心线程池:
    任务提交后首先在核心线程创建线程

  • 工作队列:当核心线程池饱满后将提交的任务放入工作队列等待
    1.ArrayBlockingQueue,有界阻塞队列
    2.LinkedBlockingQueue,无界阻塞队列
    3.SynchroniousQueue,不储存元素的队列
    4.PriorityQueue,优先级队列中

  • 最大线程池

  • 线程活动时间

  • 活动时间单位

  • 饱和策略
    AbortPolicy:当线程池满后直接抛出异常
    CallRunsPolicy:调用调用者的线程来执行任务
    DiscardOldestPolicy,丢弃队列中最近的一个任务,来执行他
    DiscardPolicy,直接丢弃,没有任何提示信息

  • 线程池创建多线程的流程
    1.任务被提交后,先看核心线程池是否已满,如果不满,直接创建新线程执行任务,如果已满,看当前是否有空闲线程,没有的话执行2
    2.将任务存放到工作队列中,在工作队列中排对等待执行,如果工作队列已满执行3
    3.将任务提交到最大线程池池中,在里面创建线程执行任务
    4.最大线程池已满,执行饱和策略

  • 线程的提交

    executor(Runnable) 和submit(Runnable /Callable)

  • 线程池的关闭

    shutdown()
    shut()

  • Executors创建的几种线程池 Executors为工具方法

    newFixedThreadPool

    1.核心线程数和最大线程数一样,
    2.工作队列是无界队列 使用场景:用于有限的资源下,控制线程个数的场景,适用于负载比较重的任务

    SingleThreadPoolExecutor

    1.单线程池,最大线程池和核心线程池一样,数量为1
    2.使用无界队列 使用场景:用于要只能实现一个

    CachedThreadPool
    1.核心线程池为0,最大线程池为MAX_INTERGE
    2.工作队列是不能储存元素的队列
    3.每次提交任务都会交给创建线程 使用场景:适合负载比较小的轻量级任务, 如果处理任务速度小于提交任务速度,会因为创建多个线程耗尽资源
    ScheduledThreadPoolExecutor
    定时调度线程池,使用DelayQueue作为工作队列、按周执行任务后有不通的处理
    scheduleAtFixedRate(任务,keepAliveTime, TimeUnit.NANOSECONDS)使用此方法来提交线程
    scheduleWithFixedDelay

你可能感兴趣的:(JavaSE基础)