1. 多线程

程序:指令集,静态的概念

进程:操作系统调动程序,是程序的一次动态执行过程,动态的概念

线程:在进程内的多条执行路径

Ps:单核的话进程都是虚拟模拟出来的,多核处理器才可以执行真正的多线程

单核通过CPU调度时间片实现虚拟模拟的多线程,比如执行main函数和GC在底层就是多线程,你执行你的,我执行我的

一个进程内部的线程共享相同的内存单元,可以访问相同的变量和对象,所以存在并发控制问题

线程和进程的区别:

1. 根本区别:进程是资源分配的单位,而线程是调度和执行的单位

2. 所处环境:多进程是指操作系统中可以有多个进程,多线程是同一个进程中有多个顺序流同时执行

3. 切换开销:每个进程拥有自己独立的代码和数据空间(进程上下文),进程切换开销大,同一个进程内的线程因为是共享的进程的共享数据,所以线程切换的开销很小

4. 分配内存:系统会为每个进程分配不同的内存区域,而却不会为线程分配,线程使用的是进程的资源

多线程的实现方法:

方法1:继承Thread类

Rabbit.java

package 多线程;/*** @author:yb* @version 创建时间:2018-12-24 下午4:14:16 类说明*/
/** 模拟龟兔赛跑 * 1.创建多线程:继承Thread+重写run()线程体* 2.使用线程:创建子类对象+对象调用start()*/
public class Rabbit extends Thread {// 线程体public void run() {for (int i = 1; i <= 100; i++) {System.out.println("兔子跑了" + i + "步");}}}
class Tortoise extends Thread {// 线程体public void run() {for (int i = 1; i <= 100; i++) {System.out.println("乌龟跑了" + i + "步");}}
}

RabbitApp.java

package 多线程;/*** @author:yb* @version 创建时间:2018-12-24 下午4:20:53 类说明*/
public class RabbitApp {public static void main(String[] args) {// 创建子类对象Rabbit rab = new Rabbit();Tortoise tor = new Tortoise();// 调用start方法,不用调用run方法这个线程体
        rab.start();tor.start();/** 为什么输出会是兔子跑了两步乌龟才开始跑呢?* 因为是虚拟模拟实现的多线程,在底层cpu的按照时间片的轮转调度的,时间片先是给兔子这个对象* 它先跑两部,然后时间片时间到了,cpu把时间片给乌龟,然后乌龟开始跑* 实现的是虚拟的多线程(CPU轮流调度)* 如果是多核计算机的话,那才是真正的多线程2*/}}

分析直接继承Thread类这种方法的优缺点:

缺点:因为java的单继承,多实现,当我们一开始继承了其他类的时候,就不能继承Thread类了

优点:好像没有什么优点

为了避免这一情况,我们通过Runnable接口实现多线程

所以我们有了方法2:通过Runnable接口实现多线程

方法2:通过Runnable接口实现多线程

在这里使用了一种设计模式:静态代理,关于静态代理可以参考我的这篇博客:https://www.cnblogs.com/yinbiao/p/10169851.html

Programmer.java:

package 多线程;/*** @author:yb* @version 创建时间:2018-12-25 下午7:05:34 类说明*/
/** 使用Runnabke创建线程*  1.类要实现Runnable接口+重写run方法体 -->真实角色*  2.创建多线程 使用静态代理的设计模式 *    1)创建真实角色*    2)创建代理角色+对真实角色的引用 *    3)调用start启动线程*/
public class Programmer implements Runnable {// 重写run方法体public void run() {for (int i = 0; i < 1000; i++) {System.out.println("第" + i + "次敲Hello world");}}
}

programmerApp.java:

package 多线程;/*** @author:yb* @version 创建时间:2018-12-25 下午7:05:52 类说明*/
public class ProgrammerApp {public static void main(String[] args) {// 1)创建真实角色Programmer pro = new Programmer();// 2)创建代理角色+对真实角色的引用Thread proxy = new Thread(pro);// 3)调用start启动线程
        proxy.start();// 另外一个线程,因为main函数也算是一个线程for (int i = 0; i < 1000; i++) {System.out.println("第" + i + "次打开wegame");}}
}

优点:

1.避免了单继承

2.方便共享资源,同一份资源,多个代理访问

共享资源的体现:(即同一个真实角色,多个代理)

代码背景:模拟人们在12306上抢火车票

Web12306.java:

package 多线程;/*** @author:yb* @version 创建时间:2018-12-25 下午7:36:44 类说明*//** 通过runnable接口实现多线程* 可以方便共享资源,同一份资源,多个代理访问* 代码背景:模拟人们在web12306上抢火车票* 共享的是num,票资源*/
public class Web12306 implements Runnable {// 100张火车票private int num = 50;// 重写run方法体public void run() {while (true) {if (num <= 0)break;System.out.println(Thread.currentThread().getName() + "抢到了火车票"+ num--);}}public static void main(String[] args) {// 真实角色Web12306 web12306 = new Web12306();// 代理角色1Thread t1 = new Thread(web12306, "顾客x");// 代理角色2Thread t2 = new Thread(web12306, "黄牛y");// 代理角色3Thread t3 = new Thread(web12306, "攻城狮z");// 启动线程
        t1.start();t2.start();t3.start();}}

记住:线程通过调用start()方法是使得该进程进入就绪状态而不是运行状态!!!

方法三:线程池实现多线程,继承Callable接口

比较复杂,但是站服务器编程中应用广泛

参考一下这篇博客更好的理解此方法:https://www.cnblogs.com/yinbiao/p/10179563.html

代码背景:

还是多线程模拟龟兔赛跑

Call.java:

package 多线程;import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;import org.omg.CORBA.INTERNAL;/*** @author:yb* @version 创建时间:2018-12-25 下午8:07:11 类说明*/
public class Call {/** 使用Callable创造线程*/public static void main(String[] args) throws InterruptedException, ExecutionException {// 创建线程池ExecutorService service = Executors.newFixedThreadPool(2);Race tortoise = new Race("乌龟",1000);Race rabbit = new Race("兔子", 500);Future<Integer> result1 = service.submit(tortoise);Future<Integer> result2 = service.submit(rabbit);Thread.sleep(3000);//主线程挂起3000ms 乌龟和兔子线程开始竞争cpu 即乌龟和兔子开始跑,跑的时间都是3000mstortoise.setFlag(false);rabbit.setFlag(false);//获取值int num1=result1.get();System.out.println("乌龟跑了"+num1+"步");int num2=result2.get();System.out.println("兔子跑了"+num2+"步");//停止服务
        service.shutdownNow();}}class Race implements Callable<Integer>{private String name;//名称private int time;//延时private int step=0;//步数public Race(String name,int time) {super();this.name=name;this.time=time;}private boolean flag= true;public int getTime() {return time;}public void setTime(int time) {this.time = time;}public boolean isFlag() {return flag;}public void setFlag(boolean flag) {this.flag = flag;}public int getStep() {return step;}public void setStep(int step) {this.step = step;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer call() throws Exception{while(flag) {Thread.sleep(time);step++;    }return step;}
}

分析:

通过继承Callable接口实现的多线程,可以对外声明异常和返回值,这是前面两个方法所不能实现的,但是此方法复杂繁琐

END!

转载于:https://www.cnblogs.com/yinbiao/p/10175988.html

JAVA之多线程概念及其几种实现方法优劣分析相关推荐

  1. Java面试之多线程:Java创建多线程为什么只有一种方式?

    关于线程的创建,其实我一直都有话说,于是今天,我来开个头.今天依旧一样,长话短说,只谈创建多线程.你好,我是fntp!今天要跟大家分享的是博主最近面试Java实习所遇到的一些问题!那就是经常性被问到的 ...

  2. JAVA中线程同步的几种实现方法

    JAVA中线程同步的几种实现方法 一.synchronized同步的方法: 1.synchronized同步方法 即有synchronized关键字修饰的方法. 由于java的每个对象都有一个内置锁, ...

  3. java调用javascript函数_[Java教程]JavaScript函数的4种调用方法详解

    [Java教程]JavaScript函数的4种调用方法详解 0 2016-08-09 00:00:12 在JavaScript中,函数是一等公民,函数在JavaScript中是一个数据类型,而非像C# ...

  4. 多线程——多线程同步的三种实现方法

    当使用多线程访问同一个资源的时候,非常容易出现线程安全的问题(例如,当多个线程同时对一个数据进行修改的时候,会导致某些线程对数据的修改丢失). 因此,需要采用同步机制来解决这种问题.而Java主要提供 ...

  5. java map集合遍历方法,Java的Map集合的三种遍历方法

    集合的一个很重要的操作---遍历,学习了三种遍历方法,三种方法各有优缺点~~ 1. package com.myTest.MapText; import java.util.Collection; i ...

  6. 详解软件测试中白盒测试基本概念及四种白盒测试方法以及六种逻辑覆盖法(语句覆盖、判定覆盖、条件覆盖、判定条件覆盖、条件组合覆盖、路径覆盖)

    在这篇文章中,我们将讲解白盒测试的基本概念,以及四大常用的白盒测试方法. 一.白盒测试基本概念 1.白盒测试的定义 白盒测试又称为结构测试或逻辑驱动测试,它是把测试对象看成一个透明的盒子,它允许测试人 ...

  7. Java中多线程概念详解

    在操作系统中,两个比较容易混淆的概念是线程(thread)与进程(process).操作系统中的进程是一个计算机程序的运行实例.计算机程序中包含了需要执行的指令,而进程则表示正在执行的指令,对同一个计 ...

  8. java获取多线程执行结果几种方式小结

    前言 在使用多线程的场景中,经常需要获取多线程的执行结果,有的甚至还需要合并不同线程的执行结果进行后续的业务逻辑处理等,下面对常用的几种获取与合并多线程的执行结果的方式做一下小结 1.thread.j ...

  9. Java里阻塞线程的三种实现方法

    在日常开发中,我们有时会遇到遇到多线程处理任务的情况,JDK里提供了便利的 ThreadPoolExecutor以及其包装的工具类Executors.但是我们知道 ExecutorService.ex ...

最新文章

  1. 50万年薪程序员,被百万网民怒喷后,却迎来大撕逼
  2. linux 开机启动设置密码,Linux下Redis设置密码及开机自启动
  3. 分页的limit_Presto分页功能概述
  4. 一次PHP中SQL的Where子句无效问题的解决之旅
  5. 我见过不少赚了钱,投资孵化一堆店铺的,一般而言后续发展都会出问题的
  6. GitLab容器注册服务已集成于Docker容器
  7. Windows Driver开发_安装与配置环境
  8. 【渝粤教育】国家开放大学2018年秋季 0700-22T中级会计实务(一) 参考试题
  9. Android ActivityManager一些API介绍
  10. 微信计步器怎么不计步_微信运动不显示步数解决方法
  11. CSS揭秘读书笔记-第一章 引言
  12. 2021年12月国产数据库大事记-墨天轮
  13. 小鸟壁纸 删除 卸载 流氓 鲁大师 360 软件 弹窗 后台
  14. 在Matlab中构建最大带权生成树
  15. 关于photoshop软件的177个小技巧
  16. 在matlab中建模基准地形和山峰
  17. 程序员年底好找工作吗?
  18. 苹果计算机如何出现关机界面,让你的iPhone开关机重启和电脑一样显示进度条
  19. /usr/include/linux/if_ppp.h:117: error: expected specifier-qualifier-list before 'aligned_u64' 解决方式
  20. LaTeX易忘符号小结,如何打限制条件?如何打分段函数?如何打花体英文?

热门文章

  1. 集算器协助MongoDB计算之交叉汇总
  2. arcgis导入坐标点转面_arcgis矢量化建筑数据
  3. datacount+php,dataCount.php
  4. plsql突然无法连接数据库,原来是tnsnames.ora文件出了问题
  5. SpringBoot集成Activiti Explorer
  6. ORM框架之Mybatis(五)mybatis生成器配置文件说明以及生成的类的说明
  7. 两次被简书签约作者拉黑的经历
  8. java程序给输出汉字_java面试题目编写一个java程序,实现拼音转成对应汉字功能。...
  9. php mysql查询例子_php mysql一个查询优化的简单例子
  10. VirtualBox启动失败,The VM session was aborted.