当前位置:网站首页 > Java基础 > 正文

java线程基础课程



目录

一.线程创建

线程基础知识介绍

创建方法一:继承Thread类

创建方法二:实现Runnable接口

创建方法三:实现Callable接口;线程池

线程池

Callable接口实现多线程

二.线程状态

线程状态

java线程基础课程

线程状态转换

代码演示

三.线程优先级

四.用户线程,守护线程

五.线程同步

同步方法

同步代码块

可重入锁ReentrantLock


详细讲解,强烈建议收藏!!!

一.线程创建

线程基础知识介绍

什么是线程?为什么要使用线程?

        在没有使用到线程的程序中,我们总是只能串行的执行程序,也就是我们的程序一次性只能进行一个操作。而我们使用微信进行视频聊天的时候,我们可以一边视频,一边和其他人打字聊天。这就是多线程,可以一个线程负责视频聊天,一个线程负责打字聊天,使用的任然是一个程序。在日常使用场景中,多线程是必要的。

创建方法一:继承Thread类

        Thread单词意思就是线程的意思,是Java提供的一个线程类。可以自己创建一个类然后继承Thread,重写run方法。run方法写入你想要进行多线程运行的代码。

        通过你建的类,实例化一个对象;通过这个对象调用start()方法,该对象就可以进行多线程操作了。

创建步骤:

        1.继承Thread类,重写run方法

        2.实例化一个对象,调用start方法(就是执行run函数里面的内容)

代码演示:

 

        运行结果发现,Thread1线程和Thread2线程轮流上处理机执行,由此可知该段程序确实实现了多线程操作 

创建方法二:实现Runnable接口

        Runnable是一个接口,该接口是一个函数式接口(不知道函数式接口的伙伴,可以看看我上一篇博客哦),只有一个抽象方法run

创建方法一的Thread类就是实现了Runnable接口,查看源码如下图:

        那为什么已经有Java开发人员已经给我们封装好的Thread类,有更多的方法可以供我们调用,我们还要用Runnable接口来实现线程,不是很冗余嘛,容我卖个关子,会在代码中解释。

创建步骤:

        1 创建一个类实现Runnable接口,重写run方法

        2 通过该类实例化对象

        3 将实例化的对象作为参数传到Thread实现线程,再调用start方法

 

上面代码用到的构造器: 

        细心的伙伴在运行代码的时候会发现,票数可能出现负数的情况,这是明显的异常,原因是多个线程买了同一张票,为了解决这个问题,需要用到线程同步的知识,将在后续章节介绍。

创建方法三:实现Callable接口;线程池

        Callable也是一个接口,可以使用到线程池。当多线程场景下,我们一直创建或者销毁线程,对性能影响都很大,如果我们提前创建好多个线程,放入线程池,使用时直接获取,使用完放回池中,就可以避免一直创建、销毁,达到重复利用。

线程池

ExecutorService     线程池接口

常用方法:

        void execute(Runnable command); 执行任务,没有返回值,一般用来执行Runnable

        <T> Future<T> submit(Callable<T> task);执行任务,有返回值,一般用来执行Callable

        void shutdown();关闭连接池

Executors  该类用于创建线程池

Callable接口实现多线程

        实现callable接口需要返回值类型 ,而上述两种方法是不需要返回值的。不同与上述两种方法,实现Callable需要重写call方法,而不是run方法,并且call方法需要抛出异常。

创建步骤:

        1 创建一个类实现Callable接口,重写call方法

        2 创建目标对象,即通过该类实例化对象

        3 创建执行的服务,可通过实现线程池来创建

        4 提交执行 callable为submit方法

        5  获取结果

        6 关闭服务

 

二.线程状态

线程状态

创建:当线程被创建时为创建状态

就绪:线程被分配了除处理机以外的所有资源

运行:线程正在处理机上运行

阻塞:线程还缺乏除处理机以外的其他资源导致无法继续执行

终止:线程执行结束

 

线程状态转换

创建到就绪:线程被分配足够资源就到了就绪状态,可以随时上处理机,理论上创建好的线程调用start方法即可进入就绪状态

就绪到运行:该转换可能又操作系统自行安排,也可通过程序定义的抢占来完成,join方法就是抢占方法,只有join的线程执行完,其他的才能执行

运行到就绪大有可能就是有线程抢占了处理机资源,也可以使用yield方法线程自己礼让

运行到阻塞:除了线程缺乏资源只能阻塞,也可以调用sleep方法,线程自行休眠

代码演示

下面对上述及其他线程状态有关方法演示:

 

三.线程优先级

上文介绍线程状态切换中有个抢占算法join,什么时候需要抢占呢?其中有个使用场景就是,线程优先级是不同的,高优先级可以抢占低优先级的处理机资源。

Java线程按照数值划分等级,从1~10数值越大等级越高。

可以通过getPriority()这个方法获取线程的优先级

通过setPriority()设置线程的优先级,数值可以从0~10

还提供了三种常量可供选择。

未设置优先级,默认为5.

下面进行代码演示

 

 

四.用户线程,守护线程

 

五.线程同步

        多个线程操作同一个对象,就可能造成同步问题,如上文买票,可能多个线程对同一张票进行操作。解决方案可以让多个线程排队 ,,锁唯对操作对象的线程上锁一,就能避免同步问题

同步方法

使用synchronized修饰一个方法,就实现了同步方法,整个方法体都会进行同步;同时只会有一个线程执行这个方法。实际就是对这个方法加上了锁,锁唯一,有一个线程执行了这个方法,就上锁了,其他线程不能进入,就解决了同步问题。

下面优化代码,解决上文遗留的买票问题

 

同步代码块

使用synchronized定义一段代码块,对一段代码块或者代码块里的共享变量进行上锁。

上文buy方法也可以用同步代码块实现。

 

在取钱场景中,一个账户,同时在手机端和ATM机上取钱 ,也存在同步问题。账户就作为了共享变量,多个线程都可以进行操作。此时将取钱方法使用synchronized修饰,变为同步方法,由于对共享变量更新不及时,依然可能存在同步问题。

此时使用同步代码块对共享变量进行上锁可以完全解决同步问题。

 

执行结果

 

依然存在问题,使用同步代码块:

 

 得到结果

同步问题解决。 

        在实际开发中,可以尽量使用同步代码块,一个方法体并非所有部分都需要上锁,使用同步代码块更加灵活。并且同步代码块我们可以自由选择锁,对于共享变量的处理,使用同步代码块能更好解决问题。

可重入锁ReentrantLock

同步代码块、同步方法都是系统帮助我们上锁,解锁。可重入锁可以显示的上锁,解锁。

 

如有帮助,烦请点赞关注! 

版权声明


相关文章:

  • java 面试基础复习2024-11-03 17:26:01
  • 大一java基础测试题2024-11-03 17:26:01
  • 《分布式java应用基础与实践2024-11-03 17:26:01
  • java基础学习路线图2024-11-03 17:26:01
  • Java并发基础总结2024-11-03 17:26:01
  • java基础的参考文献2024-11-03 17:26:01
  • 深圳java零基础2024-11-03 17:26:01
  • java语法基础知识csdn2024-11-03 17:26:01
  • java技术基础 异步处理2024-11-03 17:26:01
  • 美的java基础笔试题2024-11-03 17:26:01