网站维护意义,淮安建设工程协会网站查询,客源引流推广,网页设计师证书怎么考?文章目录 ⭐️写在前面的话⭐️一、线程简介1.1 进程1.2 线程1.3 多线程和多进程的区别1.4 总结 二、继承实现2.1 继承Thread类例子#xff1a;网图下载 2.2 实现Runnable接口 (推荐)案例#xff1a;火车站买票问题案例#xff1a;龟兔赛跑 2.3 实现Callable接口 (了解即可)… 文章目录 ⭐️写在前面的话⭐️一、线程简介1.1 进程1.2 线程1.3 多线程和多进程的区别1.4 总结 二、继承实现2.1 继承Thread类例子网图下载 2.2 实现Runnable接口 (推荐)案例火车站买票问题案例龟兔赛跑 2.3 实现Callable接口 (了解即可)案例下载网图Runnable和Callable的区别: 三、线程知识拓展3.1 静态代理模式案例结婚 3.2 简介Lamda表达式**函数式接口**只包含唯一一个抽象方法的接口,我们可以通过Lambda表达式来创建该接口的对象。**五种改进的变化****Lambda表达式简化** 四、线程状态4.0 线程的状态简介4.1 停止线程4.24.3 五、线程同步4.14.24.3 六、线程通信问题5.15.25.3 七、高级主题4.1 停止线程4.24.3 五、线程同步4.14.24.3 六、线程通信问题5.15.25.3 七、高级主题 ⭐️写在前面的话⭐️ 博客主页 程序员好冰 欢迎 【点赞 关注 收藏⭐️ 留言】 本文由 程序员好冰 原创CSDN 首发 入站时间 2022 年 07 月 13 日 ✉️ 是非不入松风耳花落花开只读书。 推荐书籍《Java编程思想》《Java 核心技术卷》 参考在线编程网站牛客网力扣 作者水平很有限如果发现错误一定要及时告知作者哦感谢感谢 一、线程简介 多任务本质大脑在同一时间只做了同一件事情 多线程公路的多条车道 普通方法只有主线程一条执行路径 多线程多条执行路径主线程和子线程并行交替执行 1.1 进程
一个在内存中运行的应用程序。每个进程都有自己独立的一块内存空间一个进程可以有多个线程比如在Windows系统中一个运行的xx.exe就是一个进程。
1.2 线程
进程中的一个执行任务控制单元负责当前进程中程序的执行。一个进程至少有一个线程一个进程可以运行多个线程多个线程可共享数据。
1.3 多线程和多进程的区别
多进程操作系统中同时运行的多个程序
多线程在同一个进程中同时运行的多个任务
举个例子多线程下载软件可以同时运行多个线程但是通过程序运行的结果发现每一次结果都不一致。 因为多线程存在一个特性随机性。造成的原因CPU在瞬间不断切换去处理各个线程而导致的可以理解成多个线程在抢CPU资源。
多线程并不能提高运行速度但可以提高运行效率让CPU的使用率更高。但是如果多线程有安全问题或出现频繁的上下文切换时运算速度可能反而更低。 1.4 总结
线程是独立的执行路径main是主线程是系统的入口用于执行整个程序没有自己创建线程的情况下后台也会有线程如主线程、GC线程垃圾回收在一个进程中如果开辟了多个线程线程的运行由调度器安排调度调度器是与操作系统紧密相关的先后顺序是不能人为干预的对同一份资源操作时会存在资源抢夺的问题需要加入并发控制线程会带来额外的开销如CPU调度时间和并发控制开销每个线程在自己的工作内存交互内存控制不当会造成数据不一致
二、继承实现 1、Thread class--------继承Thread类 2、Runnable接口-------实现Runnable接口 3、Callable接口---------实现Callable接口 2.1 继承Thread类
不建议使用OOP单继承局限性
package space2.haobin;/*
* 创建线程方式1:
* 自定义一个类继承Thread类
* 重写run()方法
* 调用start开启线程*/
public class ThreadTest extends Thread{Overridepublic void run() {//run方法线程体for (int i 0; i 20; i) {System.out.println(我在看代码------i);}}public static void main(String[] args) {//main主线程//创建一个线程对象ThreadTest tt1 new ThreadTest();//调用start()方法开启线程tt1.start();//若此处改为调用run()即变成单线程先走run()中的“我在看代码”for (int i 0; i 200; i) {System.out.println(我在学习多线程------i);}}
}
线程不一定立即执行CPU安排调度
交替执行 例子网图下载
Apache Commons IO 也就那么回事儿吧 - 掘金 (juejin.cn)
commons-io的下载和使用_唯有一片炙热的博客-CSDN博客
package space2.haobin;import org.apache.commons.io.FileUtils;import java.io.File;
import java.io.IOException;
import java.net.URL;/*
* 联系Thread,实现多线程同步下载图片
* */
public class ThreadTest2 extends Thread{private String url;//网络图片地址private String name;//保存的文件名/*构造器*/public ThreadTest2(String url,String name){this.urlurl;this.namename;}Overridepublic void run() {WebDownloader webDownloader new WebDownloader();webDownloader.downloader(url,name);System.out.println(下载的文件名为:name);}/*主线程*/public static void main(String[] args) {ThreadTest2 t1 new ThreadTest2(https://cdnjson.com/image/Tityr,dog.jpg);ThreadTest2 t2 new ThreadTest2(https://cdnjson.com/image/TEsyr,dzq.jpg);ThreadTest2 t3 new ThreadTest2(https://cdnjson.com/image/TEkdZ,boniu.jpg);t1.start();t2.start();t3.start();}
}/*
* 下载器*/
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.2 实现Runnable接口 (推荐)
推荐使用避免单继承局限性灵活方便方便同一个对象被多个线程使用 定义MyRunnable类实现Runnable接口实现run方法,编写线程执行体创建线程对象调用start方法启动线程 package space2.haobin;/*创建线程方式2:实现Runnable接口重写run方法执行线程需要丢入Runnable接口实现类调用start方法
*/
public class ThreadTest3 implements Runnable{Overridepublic void run() {for (int i 0; i 20; i) {System.out.println(我在看代码----i);}}public static void main(String[] args) {//创建Runnable接口的实现类对象ThreadTest3 tt3 new ThreadTest3();//代理:// 创建线程对象通过线程对象来开启我们的线程/*Thread t new Thread(tt3);t.start();*//*等价于*/new Thread(tt3).start();for (int i 0; i 100; i) {System.out.println(我在学习多线程----i);}}
}案例火车站买票问题
多个线程操作同一个对象 package space2.haobin;/*
* 案例: 买火车票
* 多线程同时操作同一个对象
* */
public class ThreadTest04 implements Runnable{private int ticketNums 10;Overridepublic void run() {while(true){if(ticketNums0){break;}try {Thread.sleep(200);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println(Thread.currentThread().getName()---拿到第ticketNums--张票);}}public static void main(String[] args) {ThreadTest04 ticket new ThreadTest04();new Thread(ticket,小明).start();new Thread(ticket,老师).start();new Thread(ticket,黄牛党).start();}
}并发问题
多线程操作同一个资源的情况下线程不安全数据紊乱。
出现非法数字0或-1出现相同的数字
案例龟兔赛跑
package space2.haobin;/*模拟龟兔赛跑*/
public class Race implements Runnable{//胜利者private static String winner;Overridepublic void run() {for (int i 0; i 100; i) {/*模拟兔子休息*/if(Thread.currentThread().getName().equals(兔子) i%100){try {Thread.sleep(1);} catch (InterruptedException e) {throw new RuntimeException(e);}}if(gameOver(i)){break;//说明已经存在胜利者了可以结束比赛了}System.out.println(Thread.currentThread().getName()--- 跑了i步);}}/** 判断比赛是否结束*/private boolean gameOver(int steps){if(winner!null){//说明已经存在胜利者了return true;}else{if(steps100){winnerThread.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();}
}2.3 实现Callable接口 (了解即可) 实现Callable接口需要返回值类型重写call方法需要抛出异常创建目标对象创建执行服务:ExecutorService ser Executors.newFixedThreadPool(1);提交执行:Future result1 ser.submit(t1);获取结果boolean r1 result1.get();关闭服务ser.shutdownNow(); 案例下载网图
package space2.haobin02;import org.apache.commons.io.FileUtils;import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.*;/** 实现Callable接口,实现多线程同步下载图片* */
public class TestCallable implements Callable Boolean{private String url;//网络图片地址private String name;//保存的文件名/*构造器*/public TestCallable(String url,String name){this.urlurl;this.namename;}Overridepublic Boolean call() {WebDownloader webDownloader new WebDownloader();webDownloader.downloader(url,name);System.out.println(下载的文件名为:name);return true;}/*主线程*/public static void main(String[] args) throws ExecutionException, InterruptedException {TestCallable t1 new TestCallable(https://cdnjson.com/image/Tityr,dog.jpg);TestCallable t2 new TestCallable(https://cdnjson.com/image/TEsyr,dzq.jpg);TestCallable t3 new TestCallable(https://cdnjson.com/image/TEkdZ,boniu.jpg);//创建执行服务ExecutorService ser Executors.newFixedThreadPool(3);//提交执行FutureBoolean r1 ser.submit(t1);FutureBoolean r2 ser.submit(t2);FutureBoolean r3 ser.submit(t3);//获取返回值boolean rs1 r1.get();boolean rs2 r2.get();boolean rs3 r3.get();//关闭服务ser.shutdown();}
}/** 下载器*/
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方法出现问题);}}
}Runnable和Callable的区别:
Callable规定的方法是call(),Runnable规定的接口是run();
Callable的任务执行后可返回值,而Runnable的任务是不能有返回值的;
call方法可以抛出异常,run方法不可以
运行Callable任务可以拿到一个Future对象,表示异步计算的结果,它提供了检查是否计算完成的方法,以等待计算的完成,并检索计算的结果,通过Future对象可以了解任务执行情况,可以取消任务的执行,还可以获取执行结果
三、线程知识拓展
3.1 静态代理模式
真实对象目标对象和代理对象都要实现同一个接口代理对象要代理真实角色好处 代理对象可以做许多真实对象做不到的事情真实对象可以专注做自己的事情
案例结婚
package space2.haobin03;/*静态代理模式*/
public class StaticProxy {public static void main(String[] args) {WeddingCompany weddingCompany new WeddingCompany(new You());/*相当于婚庆公司代理你结婚*/weddingCompany.HappyMarry();/*如果不进行代理,则这样写:You you new You();you.HappyMarry();*/}}
//抽象类结婚
interface Marry{void HappyMarry();
}/*
* 模拟真实的你结婚目标
* */
class You implements Marry{Overridepublic void HappyMarry() {System.out.println(我结婚啦);}
}/*
* 模拟婚庆公司代理你结婚
* */
class WeddingCompany implements Marry{//结婚对象private Marry target;public WeddingCompany(Marry target) {this.target target;}Overridepublic void HappyMarry() {before();this.target.HappyMarry();after();}/*模拟婚前*/private void before(){System.out.println(婚前布置------);}/*模拟婚后*/private void after(){System.out.println(婚后洞房------);}
}3.2 简介Lamda表达式 好处 避免匿名内部类定义过多实质是函数式编程去掉多余的代码留下核心代码逻辑简化代码 函数式接口只包含唯一一个抽象方法的接口,我们可以通过Lambda表达式来创建该接口的对象。 public interface Runnable{public abstract void run();
}五种改进的变化 直接实现类静态内部类局部内部类匿名内部类Lambda表达式 package space2.haobin03;public class TestLambda {//2.静态内部类static class Like2 implements ILike {Overridepublic void lambda() {System.out.println(我喜欢Lambda2.);}}public static void main(String[] args) {ILike like new Like();like.lambda();like new Like2();like.lambda();//3.局部内部类class Like3 implements ILike{Overridepublic void lambda() {System.out.println(我喜欢Lambda3.);}}like new Like3();like.lambda();//4.匿名内部类like new ILike() {Overridepublic void lambda() {System.out.println(我喜欢Lambda4.);}};like.lambda();//5.lambda简化like()- System.out.println(我喜欢Lambda5.);like.lambda();}
}//定义一个函数式接口
interface ILike {void lambda();
}//1.实现类
class Like implements ILike {Overridepublic void lambda() {System.out.println(我喜欢Lambda.);}
}Lambda表达式简化
参考文章
四、线程状态 4.0 线程的状态简介 4.1 停止线程 使用退出标志使线程正常退出也就是当 run() 方法完成后线程中止。使用 stop() 方法强行终止线程但是不推荐使用这个方法该方法已被弃用。使用 interrupt 方法中断线程。 参考文章 4.2
4.3
五、线程同步 4.1
4.2
4.3
六、线程通信问题 5.1
5.2
5.3
七、高级主题 先看后赞养成习惯 先看后赞养成习惯 觉得文章写得不错的老铁们点赞评论关注走一波谢谢啦 [外链图片转存中…(img-muIWB1ub-1700896285751)]
[外链图片转存中…(img-L9bewrOX-1700896285751)]
4.1 停止线程 使用退出标志使线程正常退出也就是当 run() 方法完成后线程中止。使用 stop() 方法强行终止线程但是不推荐使用这个方法该方法已被弃用。使用 interrupt 方法中断线程。 参考文章
[外链图片转存中…(img-rj37EWtp-1700896285752)]
4.2
4.3
五、线程同步 4.1
4.2
4.3
六、线程通信问题 5.1
5.2
5.3
七、高级主题 先看后赞养成习惯 先看后赞养成习惯 觉得文章写得不错的老铁们点赞评论关注走一波谢谢啦