多线程详解
2022/8/3 6:23:50
本文主要是介绍多线程详解,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
1. 线程简介
简介 | |
---|---|
任务 | 本质上在同一时间做了一件事情。吃饭玩手机,开车打电话。 |
进程(Process) | 在操作系统中运行的程序。是执行程序的一次执行过程,动态概念。 |
程序(Thread) | 指令和数据的有序集合,本身没有任何运行的含义,静态概念。 |
线程 | 一个进程中可以包含若干个线程,一个进程中至少有一个线程。 |
多线程 | 从软件或者硬件上实现多个线程并发执行的技术。王者荣耀开黑。 |
普通方法调用和多线程调用,如图:
2. 线程实现(重点)
1. 继承Thread class
// 步骤: // 1. 自定义线程类继承Thread类 // 2. 重写run()方法,编写线程执行体 // 3. 创建线程对象,调用start()方法启动
//注意:线程开启不一定不一定立即执行,由CPU调度执行 //创建线程方式一: 继承Thread类, 重写run()方法,调用Start()开启线程。(start()方法线程同时执行) public class TestThread extends Thread { @Override public void run() { //run方法线程体 for (int i = 0; i < 20; i++) { System.out.println("我在看代码----run----" + i); } } public static void main(String[] args) { //main线程, 主线程 TestThread t1 = new TestThread(); t1.start(); //创建线程对象,调用start()方法开启线程 // new t1().start(); //创建线程对象,调用start()方法开启线程 // new t1().run(); //先执行run方法。 for (int i = 0; i < 20; i++) { System.out.println("我在学习多线程----main----" + i); } } }
2. 实现 Runable 接口
// 步骤 // 1. 定义MyRunnable类实现Runnable接口 // 2. 实现run()方法,编写线程执行体 // 3. 创建线程对象,调用start()方法启动线
/创建线程方式2: 实现runnable接口, 重写run方法, 执行线程需要将runnable实现类对象丢入Thread中, 调用Start()方法。 //runnable里面没有start()方法, 所以需要开启线程的时候, 需要借用Thread类中的Start()方法。 public class TestRunnable implements Runnable { @Override public void run() { //run方法线程体 for (int i = 0; i < 20; i++) { System.out.println("我在看代码----run----" + i); } } public static void main(String[] args) { //main线程, 主线程 TestRunnable T3 = new TestRunnable();//创建runnable接口的实现类对象 // Thread thread = new Thread(T3); //创建线程对象,通过线程对象代理开启我们的线程。 // thread.start(); //创建线程对象,通过线程对象代理开启我们的线程。 new Thread(T3).start(); //创建线程对象,通过线程对象代理开启我们的线程。 for (int i = 0; i < 20; i++) { System.out.println("我在学习多线程----main----" + i); } } }
扩展:网页下载器
-
下载jar包,编写工具类
class WebDownloader { //文件下载工具类 public void downloader(String url, String name) { //远程路径 下载名字 try { //FileUtils: 文件工具,复制url到文件 //Commons IO: 针对开发IO流功能的工具库 FileUtils.copyURLToFile(new URL(url), new File(name)); //将网络上的一个网页地址变为一个文件 } catch (IOException e) { e.printStackTrace(); System.out.println("IO异常,downloader方法下载异常。"); } } }
-
继承Thread类,重写run方法
class TestThread extends Thread { //练习Thread, 实现多线程同步下载图片。 private String url; //网络图片地址 private String name; //保存的文件名 public TestThread(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) { //main方法 TestThread2 T1 = new TestThread2("https://img3.doubanio.com/view/note/l/public/p83642840.webp","1.jpg"); TestThread2 T2 = new TestThread2("https://img3.doubanio.com/view/note/l/public/p83642840.webp","2.jpg"); TestThread2 T3 = new TestThread2("https://img3.doubanio.com/view/note/l/public/p83642840.webp","3.jpg"); T1.start(); T2.start(); T3.start(); }
完整代码
通过实现Thread类实现
class TestThread extends Thread { //练习Thread, 实现多线程同步下载图片。 private String url; //网络图片地址 private String name; //保存的文件名 public TestThread(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) { //main方法 TestThread T1 = new TestThread("https://img3.doubanio.com/view/note/l/public/p83642840.webp","1.jpg"); TestThread T2 = new TestThread("https://img3.doubanio.com/view/note/l/public/p83642840.webp","2.jpg"); TestThread T3 = new TestThread("https://img3.doubanio.com/view/note/l/public/p83642840.webp","3.jpg"); T1.start(); T2.start(); T3.start(); } }
通过实现Runnalbe接口实现
class Testrunnable implements Runnable { //练习Thread, 实现多线程同步下载图片。 private String url; //网络图片地址 private String name; //保存的文件名 public Testrunnable(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) { //main方法 Testrunnable T4 = new Testrunnable("https://img3.doubanio.com/view/note/l/public/p83642840.webp", "4.jpg"); Testrunnable T5 = new Testrunnable("https://img3.doubanio.com/view/note/l/public/p83642840.webp", "5.jpg"); Testrunnable T6 = new Testrunnable("https://img3.doubanio.com/view/note/l/public/p83642840.webp", "6.jpg"); new Thread(T4).start(); new Thread(T5).start(); new Thread(T6).start(); } }
扩展:龟兔赛跑
public class Race implements Runnable { private static String winner; //胜利者 @Override public void run() { for (int i = 1; i <= 100; i++) { //模拟兔子休息200ms if ((Thread.currentThread().getName().equals("兔子")) && (i % 10 == 0)) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } //判断比赛是否结束 boolean flag = gameOver(i); if (flag) { // System.out.println(Thread.currentThread().getName()+"-->跑了"+i+"米。"); break; } System.out.println(Thread.currentThread().getName() + "-->跑了" + i + "米"); } }
//判断是否完成比赛 private boolean gameOver(int steps) { if (winner != null) { return true; } else if (steps == 100) { winner = Thread.currentThread().getName(); System.out.println("winner is ---> " + winner); return true; } return false; } public static void main(String[] args) { Race race = new Race(); new Thread(race, "乌龟").start(); new Thread(race, "兔子").start(); } }
扩展:购买火车票
//多个线程同时操作一个对象 //发现问题: 多个线程操作同一个资源的情况下, 线程不安全, 数据紊乱。 //出现多个人抢到同一张票。 //Thread.currentThread().getName() 查看是哪个线程正在操作(当前运行线程的名字) public class TestRunnable implements Runnable{ private int ticketNums = 10; //票数 @Override public void run() { while (true) { if (ticketNums < 1) { break; } try { //模拟延迟。 Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"---->>拿到了第"+(ticketNums--)+"票。"); } } public static void main(String[] args) { TestRunnable testThread4 = new TestRunnable(); //开启3个线程处理同一资源 new Thread(testThread4,"小明").start(); new Thread(testThread4,"小红").start(); new Thread(testThread4,"黄牛").start(); } }
初识并发问题
Thread-Runnable的小结:
继承Thread类 | 实现Runnable接口 |
---|---|
子类继承Thread类具备多线程能力 | 实现接口Runnable具有多线程能力 |
启动线程:子类对象.Start() | 传入目标对象+Thread对象.Start() |
不建议使用:避免OOP单继承局限性 | 推荐使用:避免OOP单继承局限性,灵活方便,方便同一个对象被多个线程使用。 |
3. 实现Callable(了解)
// 步骤 // 1. 实现Callable接口,需要返回值类型 // 2. 重写call方法,需要抛出异常 // 3. 创建目标对象 // 4. 创建执行服务:ExecutorService ser = Executors.newFixedThreadPool(1); // 5. 提交执行:Future<Boolean> result1 = ser.submit(t1); // 6. 获取结果:boolean r1 = result1.get() // 7. 关闭服务:ser.shutdownNow()
3. 线程状态
4. 线程同步(重点)
5. 线程通信问题
6. 高级主题
这篇关于多线程详解的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南
- 2024-11-23JAVA项目部署入门:新手必读指南
- 2024-11-23Java项目部署入门:新手必看指南
- 2024-11-23Java项目部署入门:新手必读指南
- 2024-11-23Java项目开发入门:新手必读指南
- 2024-11-23JAVA项目开发入门:从零开始的实用教程
- 2024-11-23Java项目开发入门:新手必读指南