• 线程详解


               在了解线程之前我们先来看看并行和并发!

    并发(Concurrent):在同一时间间隔内交替做多个事件,多线程是并发的一种形式。

    并行(Parallel):在同一时刻做多个事件。

     

    并发:在一台处理器上“同时”处理多个任务;并行:在多台处理器上同时处理多个任务。

    所以并发编程的目标是充分的利用处理器的每一个核,以达到最高的处理性能。

    有一个清晰地比喻:
    并发:一个人同时吃三个苹果。

    并行:三个人同时吃三个苹果。

    线程和进程的区别?

    进程是程序运行和资源分配的基本单位,

    线程是进程的一个实体,是cpu调度和分派的基本单位,是比程序更小的能独立运行的基本单位;

    一个程序至少有一个进程,一个进程至少有一个线程;

    同一进程中的多个线程之间可以并发执行;

     创建线程有哪几种方式?

    ①. 继承Thread类创建线程类

    • 定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。
    • 创建Thread子类的实例,即创建了线程对象。
    • 调用线程对象的start()方法来启动该线程。

    ②. 通过Runnable接口创建线程类

    • 定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。
    • 创建 Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
    • 调用线程对象的start()方法来启动该线程。

    ③. 通过Callable和Future创建线程

    • 创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。
    • 创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。
    • 使用FutureTask对象作为Thread对象的target创建并启动新线程。
    • 用FutureTask对象的get()方法来获得子线程执行结束后的返回值。

    runnable 和 callable 的区别

    • Runnable接口中的run()方法的返回值是void,它做的事情只是纯粹地去执行run()方法中的代码而已;
    • Callable接口中的call()方法是有返回值的,是一个泛型,和Future、FutureTask配合可以用来获取异步执行的结果。

    线程有哪些状态?

    线程通常都有五种状态,创建、就绪、运行、阻塞和死亡。

    • 创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态。
    • 就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,
    •                   但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。
    •                   在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。
    • 运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。
    • 阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。sleep,suspend,wait等方法都可                    以导致线程阻塞。
    • 死亡状态。如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪

     sleep() 和 wait() 有什么区别

    • sleep():方法是线程类(Thread)的静态方法,让调用线程进入睡眠状态,让出执行机会给其他线程,等到休眠时间结束后,线程进入就绪状态和其他线程一起竞争cpu的执行时间。因为sleep() 是static静态的方法,他不能改变对象的机锁,当一个synchronized块中调用了sleep() 方法,线程虽然进入休眠,但是对象的机锁没有被释放,其他线程依然无法访问这个对象。
    • wait():wait()是Object类的方法,当一个线程执行到wait方法时,它就进入到一个和该对象相关的等待池,同时释放对象的机锁,使得其他线程能够访问,可以通过notify,notifyAll方法来唤醒等待的线程

    notify()和 notifyAll()有什么区别?

    notify()方法只随机唤醒一个 wait 线程

     notifyAll()方法唤醒所有 wait 线程

    线程的 run()和 start()有什么区别

     start()方法来启动一个线程,真正实现了多线程运行。

    run(),其实就相当于是调用了一个普通函数而已

     创建线程池有哪几种方式?

    ①. newFixedThreadPool(int nThreads)

    创建一个固定长度的线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程规模将不再变化,当线程发生未预期的错误而结束时,线程池会补充一个新的线程。

    ②. newCachedThreadPool()

    创建一个可缓存的线程池,如果线程池的规模超过了处理需求,将自动回收空闲线程,而当需求增加时,则可以自动添加新线程,线程池的规模不存在任何限制。

    ③. newSingleThreadExecutor()

    这是一个单线程的Executor,它创建单个工作线程来执行任务,如果这个线程异常结束,会创建一个新的来替代它;它的特点是能确保依照任务在队列中的顺序来串行执行。

    ④. newScheduledThreadPool(int corePoolSize)

    创建了一个固定长度的线程池,而且以延迟或定时的方式来执行任务,类似于Timer。

    线程池中 submit()和 execute()方法有什么区别?

    • 接收的参数不一样
    • submit有返回值,而execute没有
    • submit方便Exception处理

      在 java 程序中怎么保证多线程的运行安全?

    线程安全在三个方面体现:

    • 原子性:提供互斥访问,同一时刻只能有一个线程对数据进行操作,(atomic,synchronized);
    • 可见性:一个线程对主内存的修改可以及时地被其他线程看到,(synchronized,volatile);
    • 有序性:一个线程观察其他线程中的指令执行顺序,由于指令重排序,该观察结果一般杂乱无序,(happens-before原则)。
  • 相关阅读:
    深浅拷贝的区别
    python 连接mysql数据库
    前端 之HTML基础
    MySQL 多键
    MySQL 存储引擎 字段类型 约束条件
    MySQL数据库的基础知识
    全局解释器和协程
    进程剩余部分和线程
    计算机网络体系结构整理-第三单元网络交换
    计算机网络体系结构整理-第二单元IP技术
  • 原文地址:https://www.cnblogs.com/zzjlxy-225223/p/11291563.html
Copyright © 2020-2023  润新知