马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
一、线程简介
1. 什么是进程?
电脑中会有很多单独运行的程序,每个程序有一个独立的进程,而进程之间是相互独立存在的。例如图中的微信、酷狗音乐、电脑管家等等。

2. 什么是线程?
进程想要执行任务就需要依赖线程。换句话说,就是进程中的最小执行单位就是线程,并且一个进程中至少有一个线程。
那什么又是多线程呢?
提到多线程这里要说两个概念,就是串行和并行,搞清楚这个,我们才能更好地理解多线程。
- 串行,其实是相对于单条线程来执行多个任务来说的,我们就拿下载文件来举个例子:当我们下载多个文件时,在串行中它是按照一定的顺序去进行下载的,也就是说,必须等下载完A之后才能开始下载B,它们在时间上是不可能发生重叠的。

- 并行:下载多个文件,开启多条线程,多个文件同时进行下载,这里是严格意义上的,在同一时刻发生的,并行在时间上是重叠的。

了解完这两个概念之后,我们再来说什么是多线程,举个例子,比如我们打开联想电脑管家,电脑管家本身是一个程序,也可以说就是一个进程,它里面包括很多功能,电脑加速、安全防护、空间清理等等功能,如果对于单线程来说,无论我们想要电脑加速,还是空间清理,那么必须得一件事一件事的做,做完其中一件事再做下一件事,有一个执行顺序。但如果是多线程的话,我们可以在清理垃圾的同时进行电脑加速,还可以病毒查杀等等其他操作,这个就是在严格意义上的同一时刻发生的,没有先后顺序。
二、线程的创建
Java 提供了三种创建线程的方法:
- 通过继承 Thread 类本身。(重点)
- 通过实现 Runnable 接口。(重点)
- 通过 Callable 和 Future 创建线程。(了解)
1.继承Thread类
- 自定义线程类继承Thread类
- 重写run()方法,编写线程执行体
- 创建线程对象,调用start()方法启动线程
- /**
- * @ClassName ThreadDemo
- * @Description TODO 线程创建的第一种方式:继承Thread类
- * @Author ZhangHao
- * @Date 2022/12/10 11:45
- * @Version: 1.0
- */
- public class ThreadDemo extends Thread{
- @Override
- public void run() {
- //新线程入口点
- for (int i = 0; i < 100; i++) {
- System.out.println("我在玩手机:"+i);
- }
- }
- //主线程
- public static void main(String[] args) {
- //创建线程对象
- ThreadDemo demo = new ThreadDemo();
- demo.start();//启动线程
- for (int i = 0; i < 1000; i++) {
- System.out.println("我在吃饭:"+i);
- }
- //主线程和多线程并行交替执行
- //总结:线程开启不一定立即执行,由cpu调度执行
- }
- }
复制代码 写一个小小的案例:使用多线程实现网图下载
- 需要导入一个commons-io-2.11.0-bin.jar (百度搜索下载,版本不限制)
- /**
- * @ClassName ImageDownload
- * @Description TODO 网图下载
- * @Author ZhangHao
- * @Date 2022/12/10 12:55
- * @Version: 1.0
- */
- public class ImageDownload extends Thread{
- private String url;//网图下载地址
- private String name;//网图名称
-
- public ImageDownload(String url,String name){
- this.url = url;
- this.name = name;
- }
-
- @Override
- public void run() {
- WebDownloader webDownloader = new WebDownloader();
- webDownloader.downloader(url,name);
- System.out.println("下载了文件名:"+name);
- }
-
- public static void main(String[] args) {
- ImageDownload d1 = new ImageDownload("https://cn.bing.com/images/search?view=detailV2&ccid=64mezA1F&id=0567ED050842B109CEFE6D7C2E235E6513915D00&thid=OIP.64mezA1F6eYavcDWrgjHQgHaEK&mediaurl=https%3a%2f%2fimages.hdqwalls.com%2fwallpapers%2fcute-kitten-4k-im.jpg&exph=2160&expw=3840&q=Cat+Wallpaper+4K&simid=608031326407324483&FORM=IRPRST&ck=5E947A96CD5B48E39B116D48F58466AB&selectedIndex=12&ajaxhist=0&ajaxserp=0", "cat1.jpg");
- ImageDownload d2 = new ImageDownload("https://cn.bing.com/images/search?view=detailV2&ccid=qXtg4Nx0&id=A80C30163A6B55D16D61F27E632239424517705F&thid=OIP.qXtg4Nx0BUoeUP53fz_HKgHaFI&mediaurl=https%3a%2f%2fimages8.alphacoders.com%2f856%2f856433.jpg&exph=2658&expw=3840&q=Cat+Wallpaper+4K&simid=608046255722156270&FORM=IRPRST&ck=986D5F99CF8474477F4A1F2DB2850C9D&selectedIndex=25&ajaxhist=0&ajaxserp=0", "cat2.jpg");
- ImageDownload d3 = new ImageDownload("https://cn.bing.com/images/search?view=detailV2&ccid=kvYsfUHA&id=6311D8D1DC87AA4B69783A97020038B03827134D&thid=OIP.kvYsfUHAAQlEVW3Z3_EEWwHaEK&mediaurl=https%3a%2f%2fwallpapershome.com%2fimages%2fpages%2fpic_h%2f19418.jpg&exph=1080&expw=1920&q=Cat+Wallpaper+4K&simid=608016886736366855&FORM=IRPRST&ck=37C2818B80D19766E7A91B5BB7A060D6&selectedIndex=159&ajaxhist=0&ajaxserp=0", "cat3.jpg");
- d1.start();
- d2.start();
- d3.start();
- //每次执行结果有可能不一样,再次证明线程之间是由cpu调度执行
- }
- }
- //下载器
- class WebDownloader{
- //下载方法
- public void downloader(String url,String name){
- try {
- FileUtils.copyURLToFile(new URL(url),new File(name));
- } catch (IOException e) {
- e.printStackTrace();
- System.out.println("IO异常,downloader方法出现问题!");
- }
- }
- }
复制代码2. 实现Runnable接口
- 定义MyRunnable类实现Runnable接口
- 实现run()方法,编写线程执行体
- 创建线程对象,调用start()方法启动线程
- /**
- * @ClassName RunnableDemo
- * @Description TODO 线程创建的第二种方式:实现Runnable接口 (推荐使用)
- * @Author ZhangHao
- * @Date 2022/12/10 15:07
- * @Version: 1.0
- */
- //模拟抢火车票
- public class RunnableDemo implements Runnable{
- //票数
- private int ticketNums = 10;
- @Override
- public void run() {
- while (ticketNums > 0){
- try {
- //让线程睡眠一会
- Thread.sleep(10);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread().getName()+"-->抢到了第"+ticketNums--+"张票");
- }
- }
- public static void main(String[] args) {
- //创建runnable接口的实现类对象
- RunnableDemo demo = new RunnableDemo();
- //创建线程对象,通过线程对象开启线程(使用的代理模式)
- //Thread thread = new Thread(demo,"老王");
- //thread.start();
- //简写:new Thread(demo).start();
- new Thread(demo,"老王").start();
- new Thread(demo,"小张").start();
- new Thread(demo,"黄牛党").start();
- //发现问题:多个线程操作同一个资源时,线程不安全,数据紊乱。(线程并发)
- }
- }
复制代码 再来一个小小的案例:模拟《龟兔赛跑》首先得有一个赛道,兔子天生跑得快,但是兔子跑一段路就偷懒睡觉,乌龟在不停的跑,最终乌龟取得胜利!
[code]/** * @ClassName Race * @Description TODO 模拟龟兔赛跑 * @Author ZhangHao * @Date 2022/12/11 9:25 * @Version: 1.0 */public class Race implements Runnable { private static String winner;//胜利者 @Override public void run() { //设置赛道 for (int i = 1; i |