zoukankan      html  css  js  c++  java
  • 核心类库_多线程

    多线程技术概述

    线程与进程

    进程

    • 是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间

    线程

    • 是进程中的一个执行路径,共享一个内存空间,线程之间可以自由切换,并发执行。一个进程最少有一个线程
    • 线程实际上是在进程基础之上进一步划分,一个进程启动之后,里面的若干执行路径又可以划分为若干个进程

    线程池(Executors)

      如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间. 线程池就是一个容纳多个线程的容器,池中的线程可以反复使用,省去了频繁创建线程对象的操作,节省了大量的时间和资源。
    线程池的好处
    • 降低资源消耗
    • 提高响应速度
    • 提高线程的可管理性

    Java中的四种线程池 .ExecutorService

    1.缓存线程池

     1 /**
     2  * 缓存线程池.
     3  * (长度无限制)
     4  * 执行流程:
     5  *      1. 判断线程池是否存在空闲线程
     6  *      2. 存在则使用
     7  *      3. 不存在,则创建线程 并放入线程池, 然后使用
     8  */
     9 
    10 ExecutorService service=Executors.newCachedThreadPool();
    11 //向线程池中 加入 新的任务
    12 service.execute(new Runnable() {
    13     @Override public void run(){
    14         System.out.println("线程的名称:"+Thread.currentThread().getName());
    15     }
    16 });
    17 service.execute(new Runnable() { 
    18     @Override public void run(){ 
    19         System.out.println("线程的名称:"+Thread.currentThread().getName()); 
    20     } 
    21 });
    22 service.execute(new Runnable() { 
    23     @Override public void run(){ 
    24         System.out.println("线程的名称:"+Thread.currentThread().getName()); 
    25     } 
    26 });

    2.定长线程池

     1 /**
     2  * 定长线程池.
     3  * (长度是指定的数值)
     4  * 执行流程:
     5  *      1. 判断线程池是否存在空闲线程
     6  *      2. 存在则使用
     7  *      3. 不存在空闲线程,且线程池未满的情况下,则创建线程 并放入线程池, 然后使用
     8  *      4. 不存在空闲线程,且线程池已满的情况下,则等待线程池存在空闲线程
     9  */
    10 ExecutorService service = Executors.newFixedThreadPool(2); 
    11 service.execute(new Runnable() { 
    12     @Override public void run() { 
    13         System.out.println("线程的名称:"+Thread.currentThread().getName()); 
    14     } 
    15 }); 
    16 service.execute(new Runnable() { 
    17     @Override public void run() { 
    18         System.out.println("线程的名称:"+Thread.currentThread().getName()); 
    19     } 
    20 });

    3.单线程线程池

     1 /**
     2  * 效果与定长线程池 创建时传入数值1 效果一致.
     3  * 单线程线程池.
     4  * 执行流程:
     5  * 1. 判断线程池的那个线程是否空闲
     6  * 2. 空闲则使用
     7  * 3. 不空闲,则等待池中的单个线程空闲后使用
     8  */
     9 ExecutorService service = Executors.newSingleThreadExecutor(); 
    10 service.execute(new Runnable() { 
    11     @Override public void run() { 
    12         System.out.println("线程的名称:"+Thread.currentThread().getName()); 
    13     } 
    14 }); 
    15 service.execute(new Runnable() { 
    16     @Override public void run() { 
    17         System.out.println("线程的名称:"+Thread.currentThread().getName()); 
    18     } 
    19 });

    4.周期性任务定长线程池

     1 public static void main(String[] args) {
     2         /**
     3          * 周期任务 定长线程池.
     4          * 执行流程:
     5          *      1. 判断线程池是否存在空闲线程
     6          *      2. 存在则使用
     7          *      3. 不存在空闲线程,且线程池未满的情况下,则创建线程 并放入线程池, 然后使用
     8          *      4. 不存在空闲线程,且线程池已满的情况下,则等待线程池存在空闲线程
     9          *
    10          * 周期性任务执行时:
    11          *      定时执行, 当某个时机触发时, 自动执行某任务 .
    12          */
    13         ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
    14         /**
    15          * 定时执行
    16          * 参数1. runnable类型的任务
    17          * 参数2. 时长数字
    18          * 参数3. 时长数字的单位
    19          */
    20         /*service.schedule(new Runnable() {
    21             @Override public void run() {
    22                 System.out.println("俩人相视一笑~ 嘿嘿嘿");
    23             }
    24         },5,TimeUnit.SECONDS);*/
    25         /**
    26          * 周期执行
    27          * 参数1. runnable类型的任务
    28          * 参数2. 时长数字(延迟执行的时长)
    29          * 参数3. 周期时长(每次执行的间隔时间)
    30          * 参数4. 时长数字的单位
    31          */
    32         service.scheduleAtFixedRate(new Runnable() {
    33             @Override
    34             public void run() {
    35                 System.out.println("俩人相视一笑~ 嘿嘿嘿");
    36             }
    37         }, 5, 2, TimeUnit.SECONDS);
    38     }

    Runnable与Callable

     1 /**
     2      * 接口定义
     3      */
     4     //Callable接口
     5     public interface Callable<V> {
     6         V call() throws Exception;
     7     }
     8     //Runnable接口
     9     public interface Runnable {
    10         public abstract void run();
    11     }

    Callable使用步骤

    1. 编写类实现Callable接口 , 实现call方法
    1 class XXX implements Callable<T> {
    2         @Override public <T> call() throws Exception {
    3             return T;
    4         }
    5     }
    2. 创建FutureTask对象 , 并传入第一步编写的Callable类对象
    1 FutureTask<Integer> future = new FutureTask<>(callable);
    3. 通过Thread,启动线程
    1 new Thread(future).start();

    Runnable与callable相同点

    • 都是接口
    • 都可以编写多线程程序
    • 都采用Thread.start()启动程序

    Runnable与Callable不同点

    • Runnable没有返回值;Callable可以返回执行结果
    • Callable接口的call()允许抛出异常;Runnable的run()不能抛出
    Callable获取返回值
      Callalble接口支持返回执行结果,需要调用FutureTask.get()得到,此方法会阻塞主进程的继续往下执行,如果不调用不会阻塞。
  • 相关阅读:
    两个数组的交集
    左叶子之和
    下载安装python
    占位
    2020 软件工程实践 助教总结
    安装使用 QEMU-KVM 虚拟化环境(Arch Linux / Manjaro / CentOS / Ubuntu )
    #69. 新年的QAQ
    1097E. Egor and an RPG game(Dilworth定理)
    #553. 【UNR #4】己酸集合
    #2099. 「CQOI2015」标识设计(插头dp)
  • 原文地址:https://www.cnblogs.com/zhangzhongkun/p/14472757.html
Copyright © 2011-2022 走看看