Day Fifteen

线程

多任务:

可以理解为一个人同时去干几件事,就好比在上厕所的时候边大号边玩手机,这就是一个多任务的实例。再好比现在很多人中午在吃饭的时候,或者说在吃饭的时候,看一些下饭综艺或者下饭视频,一个人边吃饭边看电视就形成了多任务。

多线程:

在现实生活中可以理解为,从家到学校中间本来只有一条单车道的路,所有的机动车还有非机动车都在这一条道上行驶,就会很容易造成道路拥塞,那么上学也很容易迟到,现在市政府把这条单车道的路进行了改造扩建,改建成了双向四车道,机动车和非机动车各走各的,来向和去向的车也各走各的,就会加快这条路的通过率,那么上学也就不会迟到了。本来再单车道上行驶可以被称为单线程,那么在双向四车道上行驶可以称作多线程

进程:

在操作系统中运行的程序就是进程,比如说QQ,LOL,CSGO,CF等等。一个进程可以有多个线程,如视频里面同时听声音,看图像等等。

进程(Process)和线程(Thread)

  • 说起进程,就要提一嘴程序。程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。
  • 进程则是执行程序的一次过程,它是一个动态的概念,是系统资源分配的单位。
  • 通常在一个进程中可以包含若干个线程,当然一个进程中至少要有一个线程,不然就没有存在的意义。线程是CPU调度和执行的单位。
  • 注意:
    • 很多的多线程都是模拟出来的,真正的多线程是指有多个CPU,即多核,如服务器。
    • 如果是模拟出来的多线程,即在一个CPU的情况下,在同一个时间点,CPU只能执行一个代码,因为切换的很快,所以就造成了同时执行的假象。

线程的核心概念

  • 线程就是独立的执行路径。
  • 在程序运行时,即使自己没有创建线程,后台也会有多个线程,如main线程(主线程),gc线程(垃圾回收线程)。
  • 在一个进程中,如果开辟了多个线程,线程的运行是由调度器安排控制的,调度器是与操作系统紧密相关的,先后顺序是不能人为的干预的。
  • 对同一份资源操作的时候,会存在资源的抢夺问题,需要加入并发控制。
  • 线程会带来额外的开销,如CPU调度时间,并发控制开销。
  • 每个线程在自己的工作内存交互,内存控制不当会导致数据不一样。

线程创建

  • Thread class —> 继承Thread类
  • Runnable接口 —> 实现Runnable接口
  • Callable接口 —> 实现Callable接口
继承Thread类
package com.liuHuan.thread;//创建线程的方式之一:继承Thread类,要重写run()方法,开启的时候要用start()方法
//注意,线程开启的时候不一定马上就执行,是要由CPU来调度执行
public class TestThread extends Thread{@Overridepublic void run() {//        run方法线程体for (int i = 0; i < 200; i++) {System.out.println("这是run方法线程体------ "+i);}}public static void main(String[] args) {//        main线程,主线程
//        创建一个线程对象TestThread testThread = new TestThread();
//        调用start()方法开启线程testThread.start();for (int i = 0; i < 1000; i++) {System.out.println("main方法里的------ "+i);}}
}
我们来写一个从网上down图的程序,简单的用到了多线程。
package com.liuHuan.thread;import org.apache.commons.io.FileUtils;import java.io.File;
import java.io.IOException;
import java.net.URL;public class DownloadImage extends Thread{private String url;//图片路径private String name;//文件名
//    构造器public DownloadImage(String url,String name){this.url = url;this.name = name;}@Overridepublic void run() {WebDownloader webDownloader = new WebDownloader();webDownloader.downloader(url,name);System.out.println("图片下载完成 " + name);}public static void main(String[] args) {DownloadImage d1 = new DownloadImage("https://img-blog.csdnimg.cn/8f625b7584b849e68c59d8ca115eca7b.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2h1YW54aW4xMTA5,size_16,color_FFFFFF,t_70#pic_center", "1.jpg");DownloadImage d2 = new DownloadImage("https://img-blog.csdnimg.cn/806f479434ad4d96bc184c43d1ffd299.png#pic_center", "2.jpg");DownloadImage d3 = new DownloadImage("https://img-blog.csdnimg.cn/efa98e8e33984f9dab21350b673c1148.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2h1YW54aW4xMTA5,size_16,color_FFFFFF,t_70#pic_center", "3.jpg");d1.start();d2.start();d3.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方法有问题!");}}
}
实现Runnable接口
package com.liuHuan.thread;//创建线程方式2:实现Runnable接口,重写run()方法,执行线程的时候需要丢入接口的实现类,再调用start()方法
public class TestRunnableThread implements Runnable{//    1.implements Runnable实现接口。
//    2.重写run方法。
//    3.先创建实现类的对象,再把这个对象作为创建Thread这个对象的参数。
//    4.最后调用start方法。@Overridepublic void run() {for (int i = 0;i<200;i++) {System.out.println("......." + i);}}public static void main(String[] args) {TestRunnableThread testRunnableThread = new TestRunnableThread();new Thread(testRunnableThread).start();for (int i = 0; i < 1000; i++) {System.out.println("*****" + i);}}
}

那上面那个小练习也可用这种方式实现。

//别的地方都不用动,只需要改这两个地方
public class DownloadImage implements Runnable{new Thread(d1).start();new Thread(d2).start();new Thread(d3).start();

小结:

  • 继承Thread类

    • 子类继承Thread类具备多线程能力
    • 启动线程:子类对象.start()
    • 不建议使用:避免OOP单继承局限性。
  • 实现Runnable接口
    • 实现接口Runnable具有多线程能力
    • 启动线程:传入目标对象+Thread对象.start()
    • 推荐使用:避免单继承局限性,灵活方便,方便同一个对象被多个线程使用。

初识并发问题

package com.liuHuan.thread;public class TicketThread implements Runnable {private  int nums = 10;@Overridepublic void run() {while (true){if (nums <= 0) {break;}try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "拿到了第" + nums-- + "张票");}}public static void main(String[] args) {TicketThread ticket = new TicketThread();new Thread(ticket,"张三").start();new Thread(ticket,"李四").start();new Thread(ticket,"王五").start();}
}

这个程序在运行结束后我们会发现,有几个人拿到了同一张票,或者说拿到了第-1张,这个问题就叫做线程不安全。当多个线程在操作同一个资源的情况下,线程是不安全的,会造成数据紊乱。

案例:龟兔赛跑

package com.liuHuan.thread;public class Race implements Runnable{//    获胜者private static String winner;@Overridepublic void run() {for (int i = 0; i <= 100; i++) {//强制让它睡觉if (Thread.currentThread().getName().equals("兔子")){try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}}
//            判断比赛是否结束boolean flag = gameOver(i);if (flag){break;}System.out.println(Thread.currentThread().getName() + "-->跑了" + i + "米");}}
//    判断是否完成比赛private boolean gameOver(int meters) {//        判断是否已经存在胜利者了if (winner != null){return true;}if (meters >= 100) {winner = Thread.currentThread().getName();System.out.println("胜利者是:" + winner);return true;}return false;}public static void main(String[] args) {Race race = new Race();new Thread(race,"兔子").start();new Thread(race,"龟").start();}
}
实现Callable接口
  • 实现Callable接口,需要返回值类型
  • 重写call方法,需要抛出异常
  • 创建目标对象
  • 创建执行服务:ExecutorService ser = Executors.newFixedThreadPool(1);
  • 提交执行:Future<Boolean> result1 = ser.submit(t1);
  • 获取结果:boolean r1 = result.get();
  • 关闭服务:ser.shutdownNow();

用实现Callable接口的方式实现网图的下载

package com.liuHuan.thread;import org.apache.commons.io.FileUtils;import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.*;public class TestCallableThread implements Callable<Boolean> {private String url;private String name;public TestCallableThread(String url, String name) {this.url = url;this.name = name;}@Overridepublic Boolean call() throws Exception {WebDownload webDownload = new WebDownload();webDownload.downloader(url,name);System.out.println("下载完成: " + name);return true;}public static void main(String[] args) {TestCallableThread t1 = new TestCallableThread("https://img-blog.csdnimg.cn/8f625b7584b849e68c59d8ca115eca7b.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2h1YW54aW4xMTA5,size_16,color_FFFFFF,t_70#pic_center", "1.jpg");TestCallableThread t2 = new TestCallableThread("https://img-blog.csdnimg.cn/806f479434ad4d96bc184c43d1ffd299.png#pic_center", "2.jpg");TestCallableThread t3 = new TestCallableThread("https://img-blog.csdnimg.cn/efa98e8e33984f9dab21350b673c1148.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2h1YW54aW4xMTA5,size_16,color_FFFFFF,t_70#pic_center", "3.jpg");ExecutorService ser = Executors.newFixedThreadPool(3);Future<Boolean> r1 = ser.submit(t1);Future<Boolean> r2 = ser.submit(t2);Future<Boolean> r3 = ser.submit(t3);try {boolean rs1 = r1.get();boolean rs2 = r2.get();boolean rs3 = r3.get();} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}finally {ser.shutdownNow();}}
}
class WebDownload{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");}}
}

其实程序是差不多的,只是在最后执行的时候要创建执行服务,别的基本上没什么区别。

静态代理模式

package com.liuHuan.thread;//静态代理模式总结:
// 真实对象和代理对象要实现同一个接口
// 代理对象要代理真实角色// 好处//代理对象可以做很多真实对象做不了的事//真实对象专注于做自己的事
public class StaticProxy {public static void main(String[] args) {You you = new You();//Lamda表达式new Thread( () ->System.out.println("123")).start();new WeddingCompany(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("婚后!");}
}

Java从接触到放弃(十五)--线程、多线程、静态代理模式相关推荐

  1. JAVA架构师之路十五:设计模式之策略模式

    JAVA架构师之路十四:设计模式之模板模式 策略模式 1. 策略模式 2. 优惠券案例 3. 支付案例 人生的游戏不在于拿了一副好牌,而在于怎样去打好坏牌,世上没有常胜将军,勇于超越自我者才能得到最后 ...

  2. JAVA之旅(三十五)——完结篇,终于把JAVA写完了,真感概呐!

    JAVA之旅(三十五)--完结篇,终于把JAVA写完了,真感概呐! 这篇博文只是用来水经验的,写这个系列是因为我自己的java本身也不是特别好,所以重温了一下,但是手比较痒于是就写出了这三十多篇博客了 ...

  3. Java NIO系列教程(十 五)Java NIO Path

    转载自  Java NIO系列教程(十 五)Java NIO Path 译文链接  译者:章筱虎 Java的Path接口是Java NIO2 的一部分,是对Java6 和Java7的 NIO的更新.J ...

  4. Java学习笔记(三十五)

    在完成对C语言的学习后,我最近开始了对C++和Java的学习,目前跟着视频学习了一些语法,也跟着敲了一些代码,有了一定的掌握程度.现在将跟着视频做的笔记进行整理.本篇博客是整理Java知识点的第三十五 ...

  5. Java 数据结构和算法(十五):无权无向图

    Java数据结构和算法(十五)--无权无向图 前面我们介绍了树这种数据结构,树是由n(n>0)个有限节点通过连接它们的边组成一个具有层次关系的集合,把它叫做"树"是因为它看起 ...

  6. 云计算设计模式(十五)——管道和过滤器模式

    云计算设计模式(十五)--管道和过滤器模式 分解,执行复杂处理成一系列可重复使用分立元件的一个任务.这种模式可以允许执行的处理进行部署和独立缩放任务元素提高性能,可扩展性和可重用性. 背景和问题 一个 ...

  7. WCF技术剖析之十五:数据契约代理(DataContractSurrogate)在序列化中的作用

    如果一个类型,不一定是数据契约,和给定的数据契约具有很大的差异,而我们要将该类型的对象序列化成基于数据契约对应的XML.反之,对于一段给定的基于数据契约的XML,要通过反序列化生成该类型的对象,我们该 ...

  8. 浅谈java的静态代理模式

    嗨喽-小伙伴们XX好呀, 本章我们来介绍,java中出现的静态代理模式. 代理,对应于英语单词-----Proxy,从字面上理解,就是在实现代理目标(Target)所有的需求的同时,还能够实现代理目标 ...

  9. java设计模式--工厂模式、静态代理模式、动态代理模式

    工厂模式 代码实现: 步骤一:创建一个接口 Car.java package FactoryMode;public interface Car {public void run(); } 步骤二:创建 ...

最新文章

  1. Sql存储过程加密和解密
  2. GDCM:MD5的测试程序
  3. build tut framework on ubuntu
  4. 字符串匹配KMP算法的讲解C++
  5. java中如何切割图片_Java 切割图片代码
  6. Oracle 存储过程笔记.
  7. SQL Server 数据库数据文件、日志文件剩余可用空间不足处理方法。
  8. iOS 手势UIGestureRecognizer详解
  9. 全国银行SWIFT代码查询
  10. NLP学习03_停用词过滤、stemming、文本表示tf-idf、文本相似度
  11. Python Playwright 打包报错 Please run the following command to download new browsers
  12. python分割文本_切分文本Python
  13. js 中日期 转换成时间戳 例如2020-12-19 转换为时间戳
  14. UnityShader入门精要-屏幕后处理效果 亮度饱和度对比度、边缘检测、高斯模糊、bloom效果、运动模糊
  15. 博客开张+第1个项目:云云图书馆
  16. Linux下内存检测工具:asan
  17. 跟着狂神学SpringCloud(Rest环境搭建+Eureka服务注册与发现+ribbon+Feign负载均衡+Hystrix+服务熔断+Zuul路由网关+SpringCloud config分布)
  18. 热搜第一!刘强东回国了!
  19. Ubuntu下使用Python调用乐视三合一摄像头
  20. Java中PO、BO、VO、DTO、POJO、DAO什么意思?

热门文章

  1. 纯白魔女怎么在电脑上玩 纯白魔女电脑版玩法教程
  2. Android 中使用自定义ttf字体实现酷炫效果
  3. java发送qq消息
  4. vim复制一行不复制换行_如何在vim中换行和不换行
  5. uniapp通话录音功能
  6. python妹子图爬虫5千张高清大图突破防盗链
  7. 用cmd查看电脑连接wifi密码
  8. Dockerfile构建java8镜像
  9. matlab无c语言基础自学,matlab及c语言在潮流计算运用【毕设、无需降重】.pdf
  10. mysql-8.0.32-winx64 下载