美文网首页
初识线程

初识线程

作者: AD刘涛 | 来源:发表于2020-03-10 16:45 被阅读0次

串行

串行是指执行多个任务时,各个任务按顺序执行,完成一个之后才能进行下一个。

并发

单个处理器上来回切换任务(在物理层面并发其实还是串行,不过是在三个程序上快速的来回切换而不是一个一个执行,在用户看来就相当于三个程序同时执行,所以叫做并发!)

并行

并行指的是多个处理器同时处理多个任务。单核处理器无法做到并行。并行一定是并发,但并发不一定是并行。

同步

所谓的同步就是某一段流程同时只能有一个线程执行,其它线程需要等待。

公平锁vs非公平锁

公平锁

按照先来后到的顺序排队获取资源,那么就是公平锁

非公平锁

但假如两人并不排队,而是通过争抢获取资源,那么这就是非公平锁

悲观锁vs乐观锁

悲观锁

认为每一次自己的操作大概率会有其它线程在并发,所以自己在操作前都要对资源进行锁定,这种锁定是排他的。悲观锁的缺点是不但把多线程并行转化为了串行,而且加锁和释放锁都会有额外的开支。

乐观锁

认为每一次操作时大概率不会有其它线程并发,所以操作时并不加锁,而是在对数据操作时比较数据的版本,和自己更新前取得的版本一致才进行更新。乐观锁省掉了加锁、释放锁的资源消耗,而且在并发量并不是很大的时候,很少会发生版本不一致的情况,此时乐观锁效率会更高。

守护线程

当 JVM 中没有任何一个非守护线程时,所有的守护线程都会进入到 TERMINATED状态,JVM 退出。在 Java 中,当没有非守护线程存在时,JVM 就会结束自己的生命周期。而守护进程也会自动退出。守护线程一般用于执行独立的后台业务。比如 JAVA 的垃圾清理就是由守护线程执行。而所有非守护线程都退出了,也没有垃圾回收的需要了,所以守护线程就随着 JVM 关闭一起关闭了。

当你有些工作属于后台工作,并且你希望这个线程自己不会终结,而是随着 JVM 退出时自动关闭,那么就可以选择使用守护线程。

并发编程的三大特性

  • 原子性:所有操作要么全部成功,要么全部失败。
  • 可见性:一个线程对变量进行了修改,另外一个线程能够立刻读取到此变量的最新值
  • 有序性:代码在执行阶段,并不一定和你的编写顺序一致。

实现多线程的方法

根据oracle官方文档,有两种方法可以创建新的线程。

方法一:

一种方法是将一个类声明为Thread的子类,通过继承thread类来定义线程,且重写thread类中的run()方法。

/**
 *  用Thread方式实现线程
 */
public class ThreadStyle extends Thread {

    @Override
    public void run(){
        System.out.println("用Thread类实现线程");
    }

    public static void main(String[] args) {
        // 每new一个新线程,则会创建一个新的ThreadStyle实例对象
        ThreadStyle thread1 = new ThreadStyle();
        ThreadStyle thread2 = new ThreadStyle();
        thread1.start();
        thread2.start();
    }

}

方法二:

创建线程的另一种方法是实现Runnable接口,然后在实现类中实现run方法。


/**
 * 用Runnable方式创建线程
 */
public class RunnableStyle implements Runnable{

    public static void main(String[] args) {
        RunnableStyle runnableStyle = new RunnableStyle();
        //  不管你开辟几个线程,他们都共享runnableStyle这一个实例
        Thread thread1 = new Thread(runnableStyle);
        Thread thread2 = new Thread(runnableStyle);
        thread1.start();
        thread2.start();
    }

    @Override
    public void run() {
        System.out.println("用Runnable方法实现了线程");
    }
}

 

两种方法的比较

ThreadRunnable之间的基本区别是,通过继承Thread类定义的每个线程都创建一个唯一的对象,并与该Thread相关联。另一方面,通过实现Runnable接口定义的每个线程将共享同一个对象。

比较 THREAD RUNNABLE
基本比较 每个线程将会创建不同的对象并与之关联。 多个线程将共享同一个对象
内存 因为每新建一个线程都会创建新的对象,因此需要耗费更多的内存 由于多个线程共享同一个对象,因此使用的内存更少。
扩展 在Java中,多重继承是不允许的,因此,在一个类继承了Thread类之后,它就不能继承任何其他类了。 如果一个类定义了实现Runnable接口,那么它还有机会继承一个类。
用法 只有当用户想要覆盖thread类中的其他方法时,才必须继承thread类。 如果您只想专门定制run方法,那么实现Runnable是更好的选择。
耦合 继承Thread类引入了紧密耦合,因为该类即包含Thread类模块的代码,同时也包括我们自己新建线程部分的代码 实现Runnable接口引入了松散耦合,因为Thread类模块的代码与我们自己新建线程部分的代码是分离的。线程控制逻辑在Thread类中,业务运行逻辑在Runnable实现类中,解耦更为彻底

总结:

  1. 线程到底有几种实现方式,从不同的角度看,会有不同的答案。
  2. 典型答案是两种,分别是实现Runnable接口和继承Thread类。
  3. 但是,当我们在看原理时,你会发现,其实Thread类也是实现Runnable接口,并且看Thread类的run方法,会发现其实那两种本质都是一样的,run方法的代码如下:
@Override
public void run() {
if (target != null) { target.run();
} }

方法一和方法二,在实现多线程的本质上,并没有区别,都是实例化Thread,并且提供其执行的run方法。无论你是通过继承thread还是实现runnable接口,最终都是重写或者实现了run方法。而你真正启动线程都是通过实例化Thread,调用其start方法来新建线程。这两个方法的最主要区别在于run()方法的内容来源:

  • 方法一:最终调用target.run();
  • 方法二:run()整个都被重写
  1. 然而还有其他的实现线程的方法,例如线程池等,它们也能新建线程,但是细看源码,从没有逃出过本质,也就是实现Runnable接口和继承Thread类。
  2. 结论: 我们只能通过新建Thread类这一种方式来创建线程,但是类里面的run方法有两种方式来实现,第一种是重写run方法,第二种实现Runnable接口的run方法,然后再把该runnable实例传给Thread类。除此之外,从表面上看线程池、 定时器等工具类也可以创建线程,但是它们的本质都逃不出刚才所说的范围。

参考文档

官方文档:线程的实现方式

Thread 和 Runnable 之间的基本区别

不可不说的Java“锁”事

相关文章

  • 初识线程

    记得初学java那会,对于线程完全是处于懵逼的状态,脑子里对线程完全没有什么概念,也想象不出它是个什么东西。当时...

  • 初识线程

    串行 串行是指执行多个任务时,各个任务按顺序执行,完成一个之后才能进行下一个。 并发 单个处理器上来回切换任务(在...

  • iOS - 多线程(一):初识

    iOS - 多线程 系列文章 iOS - 多线程(一):初识iOS - 多线程(二):pthread、NSThre...

  • iOS - 多线程(二):pthread、NSThread

    iOS - 多线程 系列文章 iOS - 多线程(一):初识iOS - 多线程(二):pthread、NSThre...

  • iOS - 多线程(四):NSOperation

    iOS - 多线程 系列文章 iOS - 多线程(一):初识iOS - 多线程(二):pthread、NSThre...

  • iOS - 多线程(三):GCD

    iOS - 多线程 系列文章 iOS - 多线程(一):初识iOS - 多线程(二):pthread、NSThre...

  • Java多线程编程核心技术(1)

    第一章 java多线程技能 目标: 0、初识线程 1、线程的启动 2、使线程暂停 3、停止线程 4、线程优先级 5...

  • 初识多线程

    近几天有些时间,想来想去,决定对iOS的多线程做个总结。如果有不妥的地方大家不吝赐教!好吧,开始。 一、进程和线程...

  • 初识后台线程

    Ⅰ、看下所有后台线程 异步读写由下面两个参数控制 innodb_read_io_threads 不建议调整,...

  • 多线程初识

    线程概述 有些程序是一条直线,起点到终点;有些程序是一个圆,不断循环,直到将它切断一个运行着的程序就是一个进程或者...

网友评论

      本文标题:初识线程

      本文链接:https://www.haomeiwen.com/subject/kqqgdhtx.html