1.实现多线程

1.1简单了解多线程【理解】

是指从软件或者硬件上实现多个线程并发执行的技术。
具有多线程能力的计算机因有硬件支持而能够在同一时间执行多个线程,提升性能。

1.11多线程实现三种方式(来自jdk1.8的api)

Thread方法

Class Thread
java.lang.Object
java.lang.Thread

All Implemented Interfaces:
Runnable
已知直接子类:
ForkJoinWorkerThread


public class Thread
extends Object
implements Runnable线程是程序中执行的线程。 Java虚拟机允许应用程序同时执行多个执行线程。
每个线程都有优先权。 具有较高优先级的线程优先于优先级较低的线程执行。 每个线程可能也可能不会被标记为守护程序。 当在某个线程中运行的代码创建一个新的Thread对象时,新线程的优先级最初设置为等于创建线程的优先级,并且当且仅当创建线程是守护进程时才是守护线程。

当Java虚拟机启动时,通常有一个非守护进程线程(通常调用某些指定类的名为main的方法)。 Java虚拟机将继续执行线程,直到发生以下任一情况:

已经调用了Runtime类的exit方法,并且安全管理器已经允许进行退出操作。
所有不是守护进程线程的线程都已经死亡,无论是从调用返回到run方法还是抛出超出run方法的run 。
创建一个新的执行线程有两种方法。 一个是将一个类声明为Thread的子类。 这个子类应该重写run类的方法Thread 。 然后可以分配并启动子类的实例。 例如,计算大于规定值的素数的线程可以写成如下:


 class PrimeThread extends Thread {long minPrime;PrimeThread(long minPrime) {this.minPrime = minPrime;}public void run() {// compute primes larger than minPrime. . .}}

然后,以下代码将创建一个线程并启动它运行:

 PrimeThread p = new PrimeThread(143);p.start();

另一种方法来创建一个线程是声明实现类Runnable接口。 那个类然后实现了run方法。 然后可以分配类的实例,在创建Thread时作为参数传递,并启动。 这种其他风格的同一个例子如下所示:


 class PrimeRun implements Runnable {long minPrime;PrimeRun(long minPrime) {this.minPrime = minPrime;}public void run() {// compute primes larger than minPrime. . .}}

然后,以下代码将创建一个线程并启动它运行:

 PrimeRun p = new PrimeRun(143);new Thread(p).start();

每个线程都有一个用于识别目的的名称。 多个线程可能具有相同的名称。 如果在创建线程时未指定名称,则会为其生成一个新名称。

除非另有说明,否则将null参数传递给null中的构造函数或方法将导致抛出NullPointerException 。

Runable接口

Interface Runnable

All Known Subinterfaces:
RunnableFuture , RunnableScheduledFuture
所有已知实现类:
AsyncBoxView.ChildState , ForkJoinWorkerThread , FutureTask , RenderableImageProducer , SwingWorker , Thread , TimerTask
Functional Interface:
这是一个功能界面,因此可以用作lambda表达式或方法引用的赋值对象。


@FunctionalInterface
public interface RunnableRunnable接口应由任何类实现,其实例将由线程执行。 该类必须定义一个无参数的方法,称为run 。
该接口旨在为希望在活动时执行代码的对象提供一个通用协议。 例如, Runnable由Thread类Thread 。 活跃的只是意味着一个线程已经启动,还没有被停止。

另外, Runnable提供了一个类被激活而不是Thread Thread类化的Thread 。 一个实现类Runnable可以在不继承运行Thread实例化一个Thread实例,并在传递本身作为目标。 在大多数情况下, Runnable接口应使用,如果你只打算重写run()方法并没有其他Thread方法。 这是重要的,因为类不应该被子类化,除非程序员打算修改或增强类的基本行为。

Callable接口

Interface Callable

参数类型
V - 方法的结果类型 call
All Known Subinterfaces:
DocumentationTool.DocumentationTask , JavaCompiler.CompilationTask
Functional Interface:
这是一个功能界面,因此可以用作lambda表达式或方法引用的赋值对象。


@FunctionalInterface
public interface Callable返回结果并可能引发异常的任务。 实现者定义一个没有参数的单一方法,称为call 。
Callable接口类似于Runnable ,因为它们都是为其实例可能由另一个线程执行的类设计的。 然而,A Runnable不返回结果,也不能抛出被检查的异常。

该Executors类包含的实用方法,从其他普通形式转换为Callable类。

1.2并发和并行【理解】

  • 并行:在同一时刻,有多个指令在多个CPU上同时执行。

  • 并发:在同一时刻,有多个指令在单个CPU上交替执行。

1.3进程和线程【理解】

  • 进程:是正在运行的程序

    独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位
    动态性:进程的实质是程序的一次执行过程,进程是动态产生,动态消亡的
    并发性:任何进程都可以同其他进程一起并发执行

  • 线程:是进程中的单个顺序控制流,是一条执行路径

    ​ 单线程:一个进程如果只有一条执行路径,则称为单线程程序

    ​ 多线程:一个进程如果有多条执行路径,则称为多线程程序

1.4实现多线程方式一:继承Thread类【应用】

  • 方法介绍

    方法名 说明
    void run() 在线程开启后,此方法将被调用执行
    void start() 使此线程开始执行,Java虚拟机会调用run方法()
  • 实现步骤

    • 定义一个类MyThread继承Thread类
    • 在MyThread类中重写run()方法
    • 创建MyThread类的对象
    • 启动线程
  • 代码演示

    public class MyThread extends Thread {@Overridepublic void run() {for(int i=0; i<100; i++) {System.out.println(i);}}
    }
    public class MyThreadDemo {public static void main(String[] args) {MyThread my1 = new MyThread();MyThread my2 = new MyThread();//        my1.run();
    //        my2.run();//void start() 导致此线程开始执行; Java虚拟机调用此线程的run方法my1.start();my2.start();}
    }
    
  • 两个小问题

    • 为什么要重写run()方法?

      因为run()是用来封装被线程执行的代码

    • run()方法和start()方法的区别?

      run():封装线程执行的代码,直接调用,相当于普通方法的调用

      start():启动线程;然后由JVM调用此线程的run()方法

1.5实现多线程方式二:实现Runnable接口【应用】

  • Thread构造方法

    方法名 说明
    Thread(Runnable target) 分配一个新的Thread对象
    Thread(Runnable target, String name) 分配一个新的Thread对象
  • 实现步骤

    • 定义一个类MyRunnable实现Runnable接口
    • 在MyRunnable类中重写run()方法
    • 创建MyRunnable类的对象
    • 创建Thread类的对象,把MyRunnable对象作为构造方法的参数
    • 启动线程
  • 代码演示

    public class MyRunnable implements Runnable {@Overridepublic void run() {for(int i=0; i<100; i++) {System.out.println(Thread.currentThread().getName()+":"+i);}}
    }
    public class MyRunnableDemo {public static void main(String[] args) {//创建MyRunnable类的对象MyRunnable my = new MyRunnable();//创建Thread类的对象,把MyRunnable对象作为构造方法的参数//Thread(Runnable target)
    //        Thread t1 = new Thread(my);
    //        Thread t2 = new Thread(my);//Thread(Runnable target, String name)Thread t1 = new Thread(my,"坦克");Thread t2 = new Thread(my,"飞机");//启动线程t1.start();t2.start();}
    }
    

1.6实现多线程方式三: 实现Callable接口【应用】

  • 方法介绍

    方法名 说明
    V call() 计算结果,如果无法计算结果,则抛出一个异常
    FutureTask(Callable callable) 创建一个 FutureTask,一旦运行就执行给定的 Callable
    V get() 如有必要,等待计算完成,然后获取其结果
  • 实现步骤

    • 定义一个类MyCallable实现Callable接口
    • 在MyCallable类中重写call()方法
    • 创建MyCallable类的对象
    • 创建Future的实现类FutureTask对象,把MyCallable对象作为构造方法的参数
    • 创建Thread类的对象,把FutureTask对象作为构造方法的参数
    • 启动线程
    • 再调用get方法,就可以获取线程结束之后的结果。
  • 代码演示

    public class MyCallable implements Callable<String> {@Overridepublic String call() throws Exception {for (int i = 0; i < 100; i++) {System.out.println("跟女孩表白" + i);}//返回值就表示线程运行完毕之后的结果return "答应";}
    }
    public class Demo {public static void main(String[] args) throws ExecutionException, InterruptedException {//线程开启之后需要执行里面的call方法MyCallable mc = new MyCallable();//Thread t1 = new Thread(mc);//可以获取线程执行完毕之后的结果.也可以作为参数传递给Thread对象FutureTask<String> ft = new FutureTask<>(mc);//创建线程对象Thread t1 = new Thread(ft);String s = ft.get();//开启线程t1.start();//String s = ft.get();System.out.println(s);}
    }
    
  • 三种实现方式的对比

    • 实现Runnable、Callable接口

      • 好处: 扩展性强,实现该接口的同时还可以继承其他的类
      • 缺点: 编程相对复杂,不能直接使用Thread类中的方法
    • 继承Thread类
      • 好处: 编程比较简单,可以直接使用Thread类中的方法
      • 缺点: 可以扩展性较差,不能再继承其他的类

1.7设置和获取线程名称【应用】

  • 方法介绍

    方法名 说明
    void setName(String name) 将此线程的名称更改为等于参数name
    String getName() 返回此线程的名称
    Thread currentThread() 返回对当前正在执行的线程对象的引用
  • 代码演示

    public class MyThread extends Thread {public MyThread() {}public MyThread(String name) {super(name);}@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println(getName()+":"+i);}}
    }
    public class MyThreadDemo {public static void main(String[] args) {MyThread my1 = new MyThread();MyThread my2 = new MyThread();//void setName(String name):将此线程的名称更改为等于参数 namemy1.setName("高铁");my2.setName("飞机");//Thread(String name)MyThread my1 = new MyThread("高铁");MyThread my2 = new MyThread("飞机");my1.start();my2.start();//static Thread currentThread() 返回对当前正在执行的线程对象的引用System.out.println(Thread.currentThread().getName());}
    }
    

1.8线程休眠【应用】

  • 相关方法

    方法名 说明
    static void sleep(long millis) 使当前正在执行的线程停留(暂停执行)指定的毫秒数
  • 代码演示

    public class MyRunnable implements Runnable {@Overridepublic void run() {for (int i = 0; i < 100; i++) {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "---" + i);}}
    }
    public class Demo {public static void main(String[] args) throws InterruptedException {/*System.out.println("睡觉前");Thread.sleep(3000);System.out.println("睡醒了");*/MyRunnable mr = new MyRunnable();Thread t1 = new Thread(mr);Thread t2 = new Thread(mr);t1.start();t2.start();}
    }
    

1.9线程优先级【应用】

  • 线程调度

    • 两种调度方式

      • 分时调度模型:所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间片
      • 抢占式调度模型:优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的 CPU 时间片相对多一些
    • Java使用的是抢占式调度模型

    • 随机性

      假如计算机只有一个 CPU,那么 CPU 在某一个时刻只能执行一条指令,线程只有得到CPU时间片,也就是使用权,才可以执行指令。所以说多线程程序的执行是有随机性,因为谁抢到CPU的使用权是不一定的

  • 优先级相关方法

    方法名 说明
    final int getPriority() 返回此线程的优先级
    final void setPriority(int newPriority) 更改此线程的优先级线程默认优先级是5;线程优先级的范围是:1-10
  • 代码演示

    public class MyCallable implements Callable<String> {@Overridepublic String call() throws Exception {for (int i = 0; i < 100; i++) {System.out.println(Thread.currentThread().getName() + "---" + i);}return "线程执行完毕了";}
    }
    public class Demo {public static void main(String[] args) {//优先级: 1 - 10 默认值:5MyCallable mc = new MyCallable();FutureTask<String> ft = new FutureTask<>(mc);Thread t1 = new Thread(ft);t1.setName("飞机");t1.setPriority(10);//System.out.println(t1.getPriority());//5t1.start();MyCallable mc2 = new MyCallable();FutureTask<String> ft2 = new FutureTask<>(mc2);Thread t2 = new Thread(ft2);t2.setName("坦克");t2.setPriority(1);//System.out.println(t2.getPriority());//5t2.start();}
    }
    

1.10守护线程【应用】

  • 相关方法

    方法名 说明
    void setDaemon(boolean on) 将此线程标记为守护线程,当运行的线程都是守护线程时,Java虚拟机将退出
  • 代码演示

    public class MyThread1 extends Thread {@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.println(getName() + "---" + i);}}
    }
    public class MyThread2 extends Thread {@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println(getName() + "---" + i);}}
    }
    public class Demo {public static void main(String[] args) {MyThread1 t1 = new MyThread1();MyThread2 t2 = new MyThread2();t1.setName("女神");t2.setName("备胎");//把第二个线程设置为守护线程//当普通线程执行完之后,那么守护线程也没有继续运行下去的必要了.t2.setDaemon(true);t1.start();t2.start();}
    }
    

Java学习--多线程相关推荐

  1. java 学习~多线程通信 使用共享变量 例子和解释

    多线程互相通信一般使用共享变量.. 完整验证代码: main 方法 public class Test5 {public static void main(String[] args) {Datax ...

  2. Java学习笔记(7)——Java基础之IO多线程网络思维导图

    Java面向对象学习笔记之:包括IO(字节流,字符流,节点流,处理流).线程(线程创建,线程控制,线程同步).网络(TCP Scoket,  UDP Scoket)(全屏观看Java学习笔记(7)-- ...

  3. 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁

    什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程的三种方式示例代码中,实现Runnable创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...

  4. Java学习笔记5-1——多线程

    目录 前言 核心概念 线程创建 继承Thread类 实现Runnable接口 上述两个方法小结 实现Callable接口 并发问题简介 静态代理模式 线程状态 线程停止(stop) 线程休眠(slee ...

  5. Java核心知识点学习----多线程中的阻塞队列,ArrayBlockingQueue介绍

    1.什么是阻塞队列? 所谓队列,遵循的是先进先出原则(FIFO),阻塞队列,即是数据共享时,A在写数据时,B想读同一数据,那么就将发生阻塞了. 看一下线程的四种状态,首先是新创建一个线程,然后,通过s ...

  6. java多线程阶乘_【java学习记录】11.用多线程实现阶乘的计算过程和结果的读取(thread类ReadThread )...

    (源码在上传的压缩包"[java学习记录]11.多线程实现阶乘计算(Thread类和Runnable接口)"中可看到,该压缩包可下载)java * 采用Thread类的子类实现线程 ...

  7. Java学习记录五(多线程、网络编程、Lambda表达式和接口组成更新)

    Java学习记录五(多线程.网络编程.Lambda表达式和接口组成更新) Java 25.多线程 25.1实现多线程 25.1.1进程 25.1.2线程 25.1.3多线程的实现 25.1.4设置和获 ...

  8. Java 学习 Day17 多线程

    Java 学习 Day17 文章目录 Java 学习 Day17 一.基本概念:程序.进程.线程 二.线程的创建和使用 三.多线程的创建,方式一:继承于Thread类 四. 创建多线程的方式二:实现R ...

  9. Java学习笔记2 多线程简单总结

    多线程简单总结 1. 相关概念 1.1 线程与进程 进程 线程 1.2 线程调度 分时调度 抢占式调度 1.3 同步与异步 同步 异步 1.4 并发与并行 并发 并行 2. 创建线程 2.1 继承Th ...

最新文章

  1. 如何运用UIControl自定义iOS中的控件
  2. linux 程序读写Env分区 --- mtdparts,/dev/mtd*,mtd_debug
  3. day05 selenium库的基础使用
  4. LeetCode 837. 新21点(动态规划)
  5. 面向区块链的高效物化视图维护和可信查询
  6. nhibernate mysql配置_NHibernate各种数据库连接参数文件配置方法说明
  7. 正则提取Swagger在线文档里面的返回实体类字段
  8. php跨域请求解决方案_解决TP接口跨域问题
  9. DB2添加数据时主键、唯一键冲突的解决方法
  10. 1.5 案例:多项式曲线拟合的比较
  11. 如何使用EasyRecovery进行深度扫描和继续扫描
  12. Spring Boot设置匹配指定后缀*.action *.do的路径
  13. ArcMap10 批量等距离分割线段
  14. C# 身份证号取年龄
  15. 最大速度、加速度时间,加速度、加加速度、加加速度时间
  16. 自适应盲信号处理的经典
  17. 前端向后端传参报415_ajax往后台传json格式数据报415错误
  18. web前端开发--------CSS基础教程
  19. 韩信点兵python编程_韩信点兵——编制计算机程序解决问题
  20. 讯飞离线语音合成(离线资源包)

热门文章

  1. 更好地对待时间的十条建议
  2. 字节跳动的长视频谜雾
  3. 单车车路:中国的车路双智能到底有多牛?丨曼孚科技
  4. vs2019实现asp.net对SQL Server完整的增删改查
  5. All in AI?(下)
  6. 主机与虚拟机linux 共享文件
  7. 将oracle端口1521共享_oracle如何开放1521端口
  8. 软件工程 习题三 课后作业
  9. uc/os学习之路(一) —— 初识uc/os
  10. Day137.MBG逆向工程、分页插件举例 -Mybatis