• Java_线程的概念和线程的创建的方法


    CSDN话题挑战赛第2期
    参赛话题:学习笔记

    一、线程的概念

    进程(process):操作系统上一个正在运行中的程序,进程会拥有当前程序中所有的资源数据

    线程(Thread):是一个进程内部的一个执行功能单元,每个线程都有自己独立的内存空间,

    一个进程内部可以有一到多个线程,进程只是拥有程序的资源,线程是负责执行具体任务的

    进程内的资源是被所有线程所共享的

    进程:公司 QQ

    线程:公司内部的各个部门 多个聊天窗口和不同人聊天

    二、多线程的优点

    优点:

    多线程并发执行,能提升系统的执行性能

    1、并发(Concurrent)

    操作系统会将时间片划分为很多个时间点,在每个时间点上只允许一个线程获取CPU

    并进入cpu中执行他的任务,执行一段时间后,就退出cpu,下一个线程再获取cpu进入,

    轮流切换来执行任务,因为时间片被切分的足够细,所以宏观上看是多个线程在同时进行的。

    这种现象被称为并发,并发并不是真正意义上的同时

    2,并行(parlen)

    真正意义上的同时,这个过程只会出现在多核cpu上,多核cpu可以在一个时间内同时去执行多件事

    缺点:

    多线程在同一资源进行操作时,可能会发生线程并发问题,导致数据不安全,可以通过加锁来解决

    三、线程的创建

    1、继承Thread

    1》创建一个类继承Thread,该类实例代表一个线程

    2》重写run() 方法,在方法中写该线程主要执行的具体任务

    3》创建线程实例

    4》调用Start()启动线程

    2、实现Runnable

    1》创建一个类实现Runnable接口,该类实力代表线程要执行的任务、

    2》重写run() 方法,在方法中写具体任务

    3》创建任务对象

    4》创建一个线程对象,将该任务对象交给线程

    5》调用Start()启动线程

    注意:

    线程调用了start()方法之后不会立即运行,而是处于就绪状态,等待CPU为其分配时间片,

    只有获得了时间片才能进入cpu中执行任务,从而调用run() 方法

    四、线程池ThreadPool(创建线程的第三种方式)

    1、线程池的作用

    主要用于创建和管理若干个线程的一种容器,当我们需要执行任务时,可以从池中取出

    线程来执行,当执行完任务后,将线程返回到池中,避免频繁的去创建和销毁线程,从而

    节省空间,提升系统性能

    2、自定义线程池

    ThreadPoolExecutor pool=

    new ThreadPoolExecutor(

    核心线程数,

    最大线程数,

    超时(空闲,活跃)时间,

    超时的时间单位,

    任务队列,

    线程工厂,

    拒绝策略);

    拒绝策略类型:

    * 1》AbortPolicy:拒绝执行新的任务,并抛出异常

    * 2》CallerRunsPolicy:如果线程池没有关闭,不使用线程池中的线程

    * 也不会加入到任务队列,而是让当前线程直接调用run()方法来执行任务,

    * 如果线程池已关闭,则直接丢弃掉该任务不执行

    * 3》DiscardOldestPolicy: 如果线程池没有关闭,将任务队列中存放最久的任务

    * (队首元素)移除掉,并将新的任务加入到任务队列中,如果线程池已经关闭

    * 则直接丢弃掉该任务不执行

    * 4》DiscardPolicy:拒绝执行任务,但是不会抛异常

    3、jdk自带线程

    1》单线程线程池

    ExecutorService es=Executors.newSingleThreadExecutor()

    只有一个核心线程,不允许创建非核心线程;

    等上一个任务执行完了,才能执行下一个任务

    2》固定数量线程池

    ExecutorService es=Executors.newFixedThreadPool(int n);

    传入的参数既是核心线程又是最大线程,

    也就是不允许创建非核心线程

    3》可缓存线程池

    ExecutorService es=Executors.newCachedThreadPool();

    没有核心线程,所有线程均为非核心线程

    有多少任务就会创建多少个线程

    线程最大数量为integer.max_value,

    所有非核心线程空闲时间超过60S就会被回收

    4》周期性线程池

    ExecutorService es=Executors.newScheduledThreadPool(int n);

    自己指定核心线程数

    线程最大数量为integer.max_value

    超时时间为0

    任务队列为延迟队列

    4、线程池的常用方法

    1》execute(Runnable r)

    将任务对象交给线程池,线程池会自动取出空闲线程来执行任务,

    没有空闲线程就将任务加入到任务队列中,队列满了就触发拒绝策略

    2》shutdown()

    安全关闭线程池

    只有等到线程池中所有线程都执行完任务后才会关闭

    如果还有未执行完任务,当前方法会阻塞

    3》shutdownNow();

    立即关闭线程

    无论线程池中是否还有未执行完的额任务,都会立即关闭线程池

    会导致线程池还有未执行完的任务,返回这些未执行的线程

    周期性线程中的主要方法

    1》schedule(Runnable r,long delay, TimeUnit unit)

    延迟指定时间后来执行这个r任务

    2>scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit);

    每间隔period指定的时间后来执行一次任务

    如果一个任务的执行时间超过了间隔时间,

    那么在一个任务执行完成红立即执行下一个任务,

    如果没有超过,那么就在指定间隔时间后执行下一个任务

    3》scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit);

    执行周期性任务

    在一个任务执行完成后,再间隔设置的时间后,

    再来执行下一个任务

    五、通过Callbale实现线程(线程第四种创建方法)

    特点:可以得到线程的执行的任务结果

    Callable使用步骤:

    1》写一个实现callable接口实现类为线程所要执行的任务,

    并指定泛型,泛型为任务的执行结果类型

    2》创建Callable任务对象,并将该对象封装在Futuretask中

    3》创建一个线程来执行Futuretask,并通过该类的get()方法来获取任务执行结果

    4》也通过调用线程池的submit()方法来执行任务,

    并将任务执行结果封装在Future类中

    并通过Future的get()方法来获取任务的执行结果

    Callable和Runnable区别

    1》Callable执行任务调用Call()方法,

    可以获取任务执行结果,也可以抛出异常

    2》Runnable执行任务调用run()方法

    不能获取任务执行结果,也不可以抛出异常

  • 相关阅读:
    C++ lambda的重载
    项目属性:服务类、货物类、工程类项目的区别
    oracle数据库报文需要先转UTF-8,再MD5,再base64加密
    分享一个基于Python的电子产品销售系统可视化销量统计java版本相同(源码+调试+开题+lw)
    单元测试(三)
    React(8)-组件ref
    区块链游戏已无利可图?
    ALevel CS里的分解和抽象
    动态规划三:常见状态与常见递推关系式
    【后端开发实习】用Nodejs操作mongodb结合Mongoose实现数据库操作
  • 原文地址:https://blog.csdn.net/m0_72254454/article/details/126878508