学习笔记,仅供参考,有错必纠


文章目录

  • 多线程
    • 多线程引入
      • 什么是线程
      • 多线程并行和并发的区别
      • Java程序运行原理
    • 多线程的实现方式
      • 多线程实现的方式1
      • 多线程程序实现的方式2
      • 以上两种实现方式的区别
    • 获取和设置线程名字
    • 获取当前线程对象
    • 休眠线程
    • 守护线程
    • 加入线程
    • 礼让线程(略)

多线程

多线程引入

什么是线程

线程是程序执行的一条路径, 一个进程中可以包含多条线程;多线程并发执行可以提高程序的效率,可以同时完成多项工作。

多线程并行和并发的区别

并行就是两个任务同时运行,就是甲任务进行的同时,乙任务也在进行;

并发是指两个任务都请求运行,而处理器只能按受一个任务,就把这两个任务安排轮流进行,由于时间间隔较短,使人感觉两个任务都在运行。

Java程序运行原理

Java命令会启动java虚拟机,启动JVM就等于启动了一个应用程序,也就是启动了一个进程;

该进程会自动启动一个主线程,然后主线程去调用某个类的main方法;

同时,JVM启动至少启动了垃圾回收线程主线程,所以是多线程的。

多线程的实现方式

多线程实现的方式1

  • 继承Thread

    • 定义继承Thread类的类;
    • 重写run方法;
    • 把新线程要做的事写在run方法中;
    • 创建线程对象;
    • 开启新线程, 内部会自动执行run方法。
  • 举个例子
package com.guiyang.restudy3;public class D2Thread {public static void main(String[] args) {MyThread mt = new MyThread();       //4,创建Thread类的子类对象mt.start();                           //5,开启线程for (int i = 0; i <= 1000; i++) {System.out.println("yyy");}}}class MyThread extends Thread {              //1,继承Threadpublic void run() {                     //2,重写run方法for (int i = 0;i <= 1000; i++) {  //3,将要执行的代码写在run方法中System.out.println("xxxxxxxxxxx");}}
}

多线程程序实现的方式2

  • 实现Runnable接口

    • 定义实现Runnable接口的类;
    • 实现run方法;
    • 把新线程要做的事写在run方法中;
    • 创建自定义的Runnable的子类对象;
    • 创建Thread对象,将刚刚创建的Runnable子类对象传入Runnable;
    • 调用start()开启新线程,Runnable的run()方法被自动调用。
  • 举个例子
package com.guiyang.restudy3;public class D3Thread {public static void main(String[] args) {MyRunnable mr = new MyRunnable();   //4,创建Runnable的子类对象Thread tr = new Thread(mr);         //5,将其当作参数传递给Thread的构造函数tr.start();                         //6,开启线程for (int i = 0; i <= 1000; i++) {System.out.println("yyy");}}}class MyRunnable implements Runnable {       //1,定义一个类实现Runnable@Overridepublic void run() {                        //2,重写run方法for (int i = 0;i <= 1000; i++) {  //3,将要执行的代码写在run方法中System.out.println("xxxxxxxxxxx");}}
}

以上两种实现方式的区别

在源码上的区别:

  • 继承Thread : 由于子类重写了Thread类的run(), 当调用start()时,直接找子类的run()方法;
  • 实现Runnable : 构造函数中传入了Runnable的引用, 成员变量记住了它, start()调用run()方法时,内部判断成员变量Runnable的引用是否为空,若不为空,编译时看的是Runnable的run()运行时执行的是子类的run()方法。

继承Thread:

  • 好处:可以直接使用Thread类中的方法,代码简单;
  • 弊端:如果某类已经有了父类,就不能再继承Thread类了。

实现Runnable接口:

  • 好处:即使自己定义的线程类有了父类也没关系,因为接口是可以多实现的;
  • 弊端:不能直接使用Thread中的方法,需要先获取到线程对象后才能得到Thread的方法,代码复杂。

获取和设置线程名字

获取名字:通过getName()方法获取线程对象的名字

设置名字:通过构造函数可以传入String类型的名字

  • 举个例子

获取线程名字:

package com.guiyang.restudy3;public class D4ThreadName {public static void main(String[] args) {new Thread("安徽财经大学") {                         //通过构造方法给name赋值public void run() {System.out.println(this.getName() + "...xxx");}}.start();new Thread("安徽医科大学") {public void run() {System.out.println(this.getName() + "....yyyyyyyy");}}.start();}}

控制台输出:

安徽财经大学...xxx
安徽医科大学....yyyyyyyy

设置线程名字:

package com.guiyang.restudy3;public class D4ThreadName {public static void main(String[] args) {Thread t1 = new Thread() {public void run() {System.out.println(this.getName() + "...yyyyyyyyy");}};Thread t2 = new Thread() {public void run() {System.out.println(this.getName() + "...xxx");}};t1.setName("财经大学");t2.setName("医科大学");t1.start();t2.start();}}

控制台输出:

财经大学...yyyyyyyyy
医科大学...xxx

获取当前线程对象

获取当前线程对象:

package com.guiyang.restudy3;public class D5GetThreadObject {public static void main(String[] args) {new Thread(new Runnable() {public void run() {for(int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + "...bb");}}}).start();Thread.currentThread().setName("我是主线程");                   //获取主函数线程的引用,并改名字System.out.println(Thread.currentThread().getName());      //获取主函数线程的引用,并获取名字}}

控制台输出:

我是主线程
Thread-0...bb
Thread-0...bb
Thread-0...bb
Thread-0...bb
Thread-0...bb

休眠线程

休眠线程:

package com.guiyang.restudy3;public class D5GetThreadObject {public static void main(String[] args) {new Thread() {public void run() {for(int i = 0; i < 5; i++) {System.out.println(getName() + "...yyyyyyyyyyy");try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}}}.start();new Thread() {public void run() {for(int i = 0; i < 5; i++) {System.out.println(getName() + "...xxx");try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}}}.start();}}

控制台输出:

Thread-0...yyyyyyyyyyy
Thread-1...xxx
Thread-0...yyyyyyyyyyy
Thread-1...xxx
Thread-0...yyyyyyyyyyy
Thread-1...xxx
Thread-0...yyyyyyyyyyy
Thread-1...xxx
Thread-0...yyyyyyyyyyy
Thread-1...xxx

守护线程

设置矩阵论线程和数值分析为守护线程,当非守护线程执行完毕后,守护线程则都自动退出:

package com.guiyang.restudy3;public class D5GetThreadObject {public static void main(String[] args) {Thread t1 = new Thread("数理统计") {public void run() {for(int i = 0; i < 3; i++) {System.out.println(getName() + "...xxx");try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}}};Thread t2 = new Thread("数值分析") {public void run() {for(int i = 0; i < 15; i++) {System.out.println(getName() + "...xxx");try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}}};Thread t3 = new Thread("矩阵论") {public void run() {for(int i = 0; i < 15; i++) {System.out.println(getName() + "...yyyyyyyy");try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}}};t2.setDaemon(true);                        //将t2和t3设置为守护线程t3.setDaemon(true);t1.start();t2.start();t3.start();}}

控制台输出:

数值分析...xxx
矩阵论...yyyyyyyy
数理统计...xxx
数值分析...xxx
数理统计...xxx
矩阵论...yyyyyyyy
矩阵论...yyyyyyyy
数理统计...xxx
数值分析...xxx
矩阵论...yyyyyyyy
数值分析...xxx

加入线程

设置当前线程暂停,等待指定的线程执行结束后,当前线程再继续:

package com.guiyang.restudy3;public class D5GetThreadObject {public static void main(String[] args) {final Thread t1 = new Thread() {public void run() {for(int i = 0; i < 6; i++) {System.out.println(getName() + "...yyyyyyyy");try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}}};Thread t2 = new Thread() {public void run() {for(int i = 0; i < 6; i++) {if(i == 2) {try {t1.join();                       //加入Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(getName() + "...xxx");}}};t1.start();t2.start();}}

控制台输出:

Thread-1...xxx
Thread-1...xxx
Thread-0...yyyyyyyy
Thread-0...yyyyyyyy
Thread-0...yyyyyyyy
Thread-0...yyyyyyyy
Thread-0...yyyyyyyy
Thread-0...yyyyyyyy
Thread-1...xxx
Thread-1...xxx
Thread-1...xxx
Thread-1...xxx

设置加入线程时间,在指定时间内插队完成后,两个线程继续交替执行:

package com.guiyang.restudy3;public class D5GetThreadObject {public static void main(String[] args) {final Thread t1 = new Thread() {public void run() {for(int i = 0; i < 7; i++) {System.out.println(getName() + "...yyyyyyyy");try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}}};Thread t2 = new Thread() {public void run() {for(int i = 0; i < 6; i++) {if(i == 2) {try {t1.join(30);                     //插队30毫秒Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(getName() + "...xxx");}}};t1.start();t2.start();}}

控制台输出:

Thread-0...yyyyyyyy
Thread-1...xxx
Thread-1...xxx
Thread-0...yyyyyyyy
Thread-0...yyyyyyyy
Thread-0...yyyyyyyy
Thread-0...yyyyyyyy
Thread-1...xxx
Thread-1...xxx
Thread-1...xxx
Thread-1...xxx
Thread-0...yyyyyyyy
Thread-0...yyyyyyyy

礼让线程(略)

使用yield让出cpu:

package com.guiyang.restudy3;public class D5GetThreadObject {public static void main(String[] args) {new MyThread2().start();new MyThread2().start();}}class MyThread2 extends Thread {public void run() {for(int i = 1; i <= 100; i++) {if(i % 10 == 0) {Thread.yield();                       //让出CPU}System.out.println(getName() + "..." + i);}}
}

第三次学JAVA再学不好就吃翔(part115)--多线程相关推荐

  1. 第三次学JAVA再学不好就吃翔(part117)--单例设计模式

    学习笔记,仅供参考,有错必纠 文章目录 多线程 单例设计模式 饿汉式 懒汉式 第三种格式 Timer类 线程的五种状态 多线程 单例设计模式 单例设计模式,即保证类在内存中只有一个对象,如何保证类在内 ...

  2. 第三次学JAVA再学不好就吃翔(part107)--字符流的拷贝

    学习笔记,仅供参考,有错必纠 文章目录 IO流 字符流的拷贝 拷贝纯文本文件 注意事项 自定义字符数组的拷贝 IO流 字符流的拷贝 拷贝纯文本文件 zzz.txt: 安徽财经大学 JAVA代码: pa ...

  3. 第三次学JAVA再学不好就吃翔(part106)--字符流

    学习笔记,仅供参考,有错必纠 文章目录 IO流 字符流输入流FileReader 字符流是什么 FileReader类构造方法 举个例子 字符流输出流FileWriter FileWriter构造方法 ...

  4. 第三次学JAVA再学不好就吃翔(part46)--Scanner类

    学习笔记,仅供参考 文章目录 Scanner类 Scanner获取数据出现的问题 Scanner类 概述 Scanner是在java.util包下的一个类,使用该类时我们需要导包.这个类被final修 ...

  5. 第三次学JAVA再学不好就吃翔(part109)--LineNumberReader类

    学习笔记,仅供参考,有错必纠 IO流 LineNumberReader类 该类继承自java.io.BufferedReader,该类可以跟踪行号的缓冲字符输入流.此类定义了方法 setLineNum ...

  6. 第三次学JAVA再学不好就吃翔(part108)--带缓冲的字符流

    学习笔记,仅供参考,有错必纠 文章目录 IO流 带缓冲的字符流 BufferedReader和BufferedWriter readLine和newLine方法 IO流 带缓冲的字符流 Buffere ...

  7. 第三次学JAVA再学不好就吃翔(part7)--基础语法之运算符

    学习笔记,仅供参考 文章目录 JAVA基础语法 运算符 算数运算符 算术运算符 ++和-- 赋值运算符 关系运算符 JAVA基础语法 运算符 什么是运算符 就是对常量和变量进行操作的符号. 运算符的分 ...

  8. 第三次学JAVA再学不好就吃翔(part113)--对象操作流

    学习笔记,仅供参考,有错必纠 对象操作流 对象操作流可以将一个对象写出, 或者读取一个对象到程序中,也就是执行了序列化和反序列化的操作. 举个例子 先构造一个Role类: package com.gu ...

  9. 第三次学JAVA再学不好就吃翔(part104)--flush和close

    学习笔记,仅供参考,有错必纠 flush和close flush方法 对于写出数据来说,当缓冲区满了之后,缓冲区中的数据会自动写出,但是当缓冲区没有满时,调用flush方法,那么缓冲区就会被刷新,数据 ...

最新文章

  1. 重磅!AI Top 30+案例评选正式启动
  2. Oracle 12C 利用Rman Duplicate搭建 Data Guard
  3. tensorflow 使用CPU而不使用GPU的问题解决
  4. excel 粘贴了HTML怎么删掉,Excel怎么删除网页上复制删不掉的文本框
  5. 推荐几款不错的写作利器
  6. C语言二叉树曲折级顺序遍历(附完整源码)
  7. arcgis渔网分割提取栅格图_【操作】ArcGIS中字段的合并、分割、提取
  8. 组合框绑定字符串数组的数据 c# 1614236088
  9. 21种代码的“坏味道”
  10. BlueHost怎样创建MySQL数据库
  11. 对话Ruby创始人松本行弘、阿里高级技术专家朴灵!
  12. 用于 3d 渲染应用程序的常见物体 IOR(折射率)值
  13. [软件发布]2007考研倒计时软件(完整版+绿色版)
  14. http代表的是什么?http代表的是什么意思
  15. FreeRTOS死机原因
  16. 美国弗吉尼亚大学计算机科学,2017美国弗吉尼亚大学计算机科学专业
  17. 浅谈ERP项目团队管理的四个方面
  18. 自动表单生成工具说明(后端、桌面、web、移动端)
  19. Python 三人斗地主手牌生成
  20. HTML5 布局标签

热门文章

  1. codelite在 ubuntu6.04下开启C++11支持
  2. 5.11 加权Gram-Schmidt 分解
  3. python编程小知识_分享Python开发中要注意的十个小贴士
  4. python为什么这么火知乎_没想到 Google 排名第一的编程语言,为什么会这么火?...
  5. python怎么导入大小字母_isort-用于对python导入的库按照字母进行排序的工具
  6. 【bzoj3160】万径人踪灭
  7. C# asp:Repeater DataSource ListT
  8. 【转】The test form is only available for requests from the local machine 解决方法
  9. HT For Web 拓扑图背景设置
  10. rabbitmq 在centos下的安装