多线程

在这里插入图片描述

前言

博客内容来源于视频—狂神说java-java多线程

(1)多线程如何执行
多线程_第1张图片
(2)进程与线程的关系
多线程_第2张图片
(3)线程与cpu
多线程_第3张图片

1.多线程创建

多线程_第4张图片
(1)通过继承Thread

  • 定义一个多线程类继承Thread类,重写run()方法
  • 在主方法中通过自定义的多线程类创建一个实例对象
  • 通过这个多线程实例对象调用start()方法开启一个新的线程

多线程_第5张图片
运行结果:
多线程_第6张图片

  • testThread1.run();是把run方法当成普通方法来执行,即只有一个主线程来处理任务;
  • testThread1.start();是通过线程对象开启一个新的子线程,这个子线程和主线程同时交替执行,由cpu调度。

实践案例:多线程下载图片
在这里插入图片描述

导入commons-io包,使用该包的FileUtils将url网络资源转为文件。
多线程_第7张图片

多线程_第8张图片
测试结果
多线程_第9张图片

(2)通过实现Runnable接口

与继承Thread类不同的地方在于要通过一个代理

  • 定义一个多线程类实现Runnable接口,重写run()方法
  • 在主方法中创建一个Runnable接口实现类的实例对象
  • 创建线程对象new Thread(),开启线程代理。将Runnable接口实现类的实例对象进行代理new Thread(Runnable接口实现类的实例对象)
  • 通过thread代理实例对象调用start()方法开启一个新的线程

多线程_第10张图片
测试结果
多线程_第11张图片
(3)两种方式的对比
多线程_第12张图片
通过实现Runnable接口实现多线程下载图片,只需要改一下线程的创建方式和线程启动方式即可。

注意:由于java是单继承,所以推荐使用实现Runnable接口的方式创建多线程。

2.多线程带来的并发问题

多线程_第13张图片

  • 在代理线程并启动时,给线程赋值一个名称;
  • 通过Thread.currentThread().getName()可以获取当前线程的名称;

由于cpu执行速度很快,于是出现了如下结果:
多线程_第14张图片
可以增大票数的值。更高级的方法是让线程短暂休眠(需要进行异常捕获):
多线程_第15张图片
测试如下:
多线程_第16张图片
发现第五张票和第七张票都被拿了两次,这就是多线程带来的并发问题,线程不安全在这里插入图片描述

3.多线程----龟兔赛跑

多线程_第17张图片

  • 定义Race线程类,实现Runnable接口,重写run方法;
  • 注意,将winner定义为static,则只会产生一个胜利者;
  • 一共一百步的比赛,对每一步进行判断,步数先到100为胜利者,跳出循环,线程不再执行任务;

多线程_第18张图片

  • 传递一个参数step,如果大于等于100,返回true。

多线程_第19张图片

  • 开启两个线程:

多线程_第20张图片
此时发现,由于cpu执行速度非常快。乌龟根本没有参加比赛,兔子就已经跑完了,因为先开启的兔子线程。现在为了让乌龟能够参加比赛,并且模拟出兔子比赛途中休息,给兔子线程开启一个短暂休眠,让线程停止片刻。
多线程_第21张图片
在这里判断兔子线程,设计的是每10步短暂休眠一次线程,这是合理的。
多线程_第22张图片
在这里插入图片描述

4.线程方法

多线程_第23张图片
多线程_第24张图片
多线程_第25张图片
(1)线程休眠

模拟网络延时:能够放大问题的发生性。sleep休眠时间到达后线程又会进入就绪状态,等待cpu调度,从而运行。
多线程_第26张图片

模拟倒计时:每隔一秒输出num减一的数字
多线程_第27张图片
要注意:这里倒计时,仅仅用了Thread这个类调用线程的sleep方法,没有任务。

系统当前时间,每一秒输出一次:
多线程_第28张图片
注意要给时间重新赋值。

(2)停止线程

你可能感兴趣的:(多线程)