day17_多线程基础

今日内容

零、 复习昨日
一、作业
二、进程与线程
三、创建线程
四、线程的API

一、复习

IO流的分类

  • 方向: 输入,输出
  • 类型: 字节(XxxStream),字符(XxxReader,XxxWriter)
  • 字节输入流类名: FileInputStream
  • 字节输出流类名: FileOutputStream
  • 字符输入流类名: FileReader
  • 字符输出流类名: FileWriter

利用try-catch-finally代码写法是重点

ArrayList和LinkedList的异同点

  • ArrayList 底层是数组,容量10,装满扩容1.5倍
  • LinkedList 底层是链表
  • 相同点: 都是存储多个元素,有序,且允许重复元素
  • 不同点: 底层实现原理不一样,AL查询更新快 LL插入删除较快

解析字符串日期为日期对象的方法签名
Date date = sdf.parse(“2020-01-01”);
Date parse(String s)

解析字符串数字为int数字的方法签名
static int parseInt(String s)

int n = Integer.parseInt(“1”);


String,Date,try-catch-finally
ArrayList,HashMap
认真,慢一点,写一遍(用法,解释,代码)到本上

二、进程与线程[了解]

进程:

一个进程就是一个应用程序,进程包含线程
一个进程至少包含一个线程,大部分都是有多条线程在执行任务(多线程),每个独立运行的程序都对应一个进程。进程是资源分配的最小单位,占用独立的内存空间和系统资源

  • qq,微信,迅雷

线程:

线程是进程内部的一个执行任务

进程内多个线程是共享进程资源,线程是资源调度的最小单位(CPU调度和分派的基本单位)

  • qq在聊天,视频,传输文件
  • 迅雷同时下载多个资源

Java程序是否是多线程的吗?
答: 是! main线程,gc垃圾回收线程

为什么需要多线程?

  • 并行处理任务,提高效率

Java程序本身,是否多线程?

  • 是,至少有一个线程是"main"线程
  • 还有一个线程是没有直接看到,但是一直在"背后"运行,垃圾回收线程(GC)

三、创建线程[重点]

Thread

创建线程的方式有很多

  • 继承Thread
  • 实现Runnable接口
  • 使用Callable 和FutureTask来完成
  • 使用线程池获得线程

3.1 继承Thread

步骤

  1. 自定义类
  2. 继承Thread
  3. 重写run方法
  4. 创建子类对象
  5. 调用start方法启动线程 [特别强调,开启新线程的方法是start]
    start方法内部执行时会调用run方法执行
public class MyThread extends Thread{// 重写方法,方法内部,就是该线程执行的任务@Overridepublic void run() {for (int i = 1; i < 101; i++) {System.out.println("MyThread --> "+i );}}
}
public class TestThread{public static void main(String[] args) {// 创建一个线程MyThread myThread = new MyThread( );// 启动线程,不是调用run()方法!!!!// 调用start方法开启新线程myThread.start();// ==============main线程执行====================for (int i = 1; i < 101; i++) {System.out.println("main     --> " + i );}// 自定义线程和主线程同时执行,并且出现资源争抢情况}
}

3.2 实现Runnable接口

步骤

  1. 自定义类
  2. 实现Runnable接口
  3. 重写run方法
  4. 创建子实现类对象
  5. 把子实现类对象当构造方法的方法参数来创建Thread对象
  6. 由thread调用start方法开启线程
public class MyRunnable implements Runnable{@Overridepublic void run() {for (int i = 1; i < 101; i++) {System.out.println("MyRunnable --> " + i);}}
}
    public static void main(String[] args) {// 4 创建实现类对象MyRunnable myRunnable = new MyRunnable( );// 5 把对象当构造方法参数,创建Thread对象Thread thread = new Thread(myRunnable);// 6 开启线程thread.start();}

匿名内部类的形式创建线程

// ============= 匿名内部类完成实现Runnable接口 ============
public class Demo4Annoy {public static void main(String[] args) {Runnable runnable = new Runnable( ) {@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println("匿名内部类 --> " + i);}}};Thread thread = new Thread(runnable);thread.start();// new Thread( new Runnable() {//     @Override//     public void run() {//         for (int i = 0; i < 100; i++) {//             System.out.println("匿名内部类 --> " + i );//         }//     }// }).start();for (int i = 0; i < 100; i++) {System.out.println("main --> " + i);}}
}

3.3 区别

继承Thread开启线程和实现Runnable接口开启线程有什么区别?


  • 一个继承,一个实现
  • 继承Thread后,直接创建对象即可调用start开启线程
  • 实现Runnable接口的子类,还需要再创建Thread类对象才可以调用strat开启线程

从使用便捷度来说,继承Thread开启线程会方便一点…因为创建完线程对象可以直接调用start开启线程

继承Thread类就限制了该类不能再继承别的类,因为类只能单继承,而实现接口的同时可以继承别的类,并且还允许多继承,所以推荐使用接口来实现多线程.

3.4 其他创建线程方式

package com.qf.thread;import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.RunnableFuture;public class Callable01 {public static void main(String[] args) throws InterruptedException, ExecutionException {// FutureTask对象用于接收线程返回值, FutureTask 实现了RunnableFuture接口// public class FutureTask<V> implements RunnableFuture<V> {}// RunnableFuture接口继承了Runnable和Future接口,后面用到的get方法来自Future接口// public interface RunnableFuture<V> extends Runnable, Future<V>{}FutureTask<String> futureTask = new FutureTask<String>(new MyCallable());Thread thread = new Thread(futureTask);thread.start();System.out.println("-----------------");// 该语句阻塞程序的执行,等待线程执行完毕,获取线程返回的数据String result = futureTask.get();System.out.println(result);}
}// 实现Callable接口的类
class MyCallable implements Callable<String> {@Overridepublic String call() throws Exception {System.out.println(Thread.currentThread().getName());Thread.sleep(5000);return "haha";}
}

四、Thread的API[熟悉]

  • void start() 开启线程,会自动run方法执行线程任务
  • void run() 执行线程的方法
    • run() 方法是start开启线程后,JVM自动调用
  • void setName(String name) 给线程设置名字
    • 也可以通过构造方法,在创建线程时指定线程名
  • String getName() 获得线程的名字
  • static Thread currentThread() 返回当前正在执行的线程对象
  • join() 加入线程,等待该线程终止
  • join(int milles) 加入线程,最大等待直到毫秒数
  • void setDaemon(boolean on) 设置守护线程
  • static void sleep(long milles) 线程休眠
    • 会让当前线程暂停执行,让出系统资源,让其他线程执行
    • 时间到,当前会继续和其他争抢资源执行
  • void stop() 结束当前线程,线程死亡(已过式)
    • 被废弃的原因是因为这个中断线程太直接太暴力…

线程名字

  • String getName()
  • void setName()
  • Thread(String name)
package com.qf.thread_api;/*** --- 天道酬勤 ---** @author QiuShiju* @desc 关于线程名字操作*/
public class Demo1 {public static void main(String[] args) {new Thread(){@Overridepublic void run() {// 给线程设置名字this.setName("驴车");// 创建线程,默认会分配名字,安装thread-x来命名System.out.println("开启新线程,线程名: " + getName());}}.start();new Thread(){@Overridepublic void run() {this.setName("火车");// 创建线程,默认会分配名字,安装thread-x来命名System.out.println("开启新线程,线程名: " + getName());}}.start();new Thread(){@Overridepublic void run() {this.setName("飞机");// 创建线程,默认会分配名字,安装thread-x来命名System.out.println("开启新线程,线程名: " + getName());}}.start();Thread thread = new Thread(){@Overridepublic void run() {}};System.out.println(thread.getName( ));thread.setName("火箭");System.out.println(thread.getName( ));/*** 还可以通过构造方法,在创建线程时指定线程名*/Thread thread5 = new Thread("子弹头"){@Overridepublic void run() {}};System.out.println("线程5-->" + thread5.getName( ));}
}

获得当前线程对象

  • static Thread currentThread()
public static void main(String[] args) {new Thread("火车"){@Overridepublic void run() {Thread t = Thread.currentThread( );System.out.println(t.getName()+",在执行..." );}}.start();/*** 获得当前正在执行的线程对象*/Thread thread = Thread.currentThread( );System.out.println("当前正在执行的线程名字是: "+thread.getName( ));
}

线程加入

  • join()
  • join(long mill)
public static void main(String[] args) {Thread t1 = new Thread("线程1"){@Overridepublic void run() {for (int i = 1; i < 1001; i++) {System.out.println(getName()+"-->"+i );}}};Thread t2 = new Thread("线程2"){@Overridepublic void run() {for (int i = 1; i < 1001; i++) {System.out.println(getName()+"-->"+i );if (i == 100) {try {// 在当前线程下加入另一个线程// 相当于"插队",直到插入的线程执行完//t1.join();// 让另外一个线程加入指定时间,到时后继续争抢t1.join(10);} catch (InterruptedException e) {e.printStackTrace( );}}}}};t1.start();t2.start();
}

守护线程

  • void setDaemon(boolean x)

  • 守护线程是指,A线程守护B线程,即B是被保护,B是重要的,当B线程结束时A线程(守护线程)会立即结束

public static void main(String[] args) {Thread hs = new Thread("皇上"){@Overridepublic void run() {for (int i = 1; i < 11; i++) {System.out.println(getName()+"工作"+i+"天" );}}};Thread fz = new Thread("妃子"){@Overridepublic void run() {for (int i = 1; i < 101; i++) {System.out.println(getName()+"工作"+i+"天" );}}};/*** 不需要设置被守护,只需要设置守护线程,其他默认就是被守护线程* 开启线程前设置*/fz.setDaemon(true);hs.start();fz.start();
}

线程休眠

  • sleep(long millis)
  • 会让当前线程陷入等待状态(阻塞)状态,让其资源让其他线程执行
public static void main(String[] args) throws InterruptedException {for (int i = 10; i > 0; i--) {System.out.println("倒计时 --> " + i );Thread.sleep(1000);}System.out.println("发射!" );
}private static void show() {Thread t1 = new Thread("线程1"){@Overridepublic void run() {for (int i = 1; i < 101; i++) {try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace( );}System.out.println(getName()+"-->"+i );}}};Thread t2 = new Thread("线程2"){@Overridepublic void run() {for (int i = 1; i < 101; i++) {System.out.println(getName()+"-->"+i );}}};t1.start();t2.start();
}

结束线程

  • void stop() 结束当前线程
  • void interrupt() 设置线程中断状态为以中断
  • boolean isInterrupt() 测试返回线程是否中断
public static void main(String[] args) {new Thread("线程2"){@Overridepublic void run() {for (int i = 1; i < 101; i++) {if (i == 15){//this.stop(); // 直接结束线程this.interrupt();// 给线程设置一个中断状态,不会真的中断线程// 结束不结束取决于线程本身执行情况}System.out.println("是否中断? "+this.isInterrupted() );System.out.println(getName()+"-->"+i );}}}.start();
}

五、线程状态[面试]

线程的几种状态:

  • 创建/新建/初始
    • new 完线程对象
  • 就绪
    • 调用start
  • 等待/阻塞
    • join()或者sleep()
  • 运行
    • 执行run()方法
  • 死亡/销毁/终止
    • run方法执行完,或者调用stop()或者interrupt()中断等

清楚状态之间的转换

image-20230802165354147

image-20230302170320045

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/179040.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

最长上升子序列模型 笔记

首先附上模板&#xff1a; #include<bits/stdc.h> #define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); #define endl \nusing namespace std;typedef pair<int, int> PII; typedef long long ll;const int N 100010;int n; int a[N], q[N];int main()…

【Ubuntu·系统·的Linux环境变量配置方法最全】

文章目录 概要读取环境变量的方法小技巧 概要 在Linux环境中&#xff0c;配置环境变量是一种常见的操作&#xff0c;用于指定系统或用户环境中可执行程序的搜索路径。 读取环境变量的方法 在Linux中&#xff0c;可以使用以下两个命令来读取环境变量&#xff1a; export 命令…

【自然语言处理(NLP)实战】LSTM网络实现中文文本情感分析(手把手与教学超详细)

目录 引言&#xff1a; 1.所有文件展示&#xff1a; 1.中文停用词数据&#xff08;hit_stopwords.txt)来源于&#xff1a; 2.其中data数据集为chinese_text_cnn-master.zip提取出的文件。点击链接进入github&#xff0c;点击Code、Download ZIP即可下载。 2.安装依赖库&am…

<C++> 优先级队列

目录 前言 一、priority_queue的使用 1. 成员函数 2. 例题 二、仿函数 三、模拟实现 1. 迭代器区间构造函数 && AdjustDown 2. pop 3. push && AdjustUp 4. top 5. size 6. empty 四、完整实现 总结 前言 优先级队列以及前面的双端队列基本上已经脱离了队列定…

场景图形管理 - (2)

裁剪平面示例(二) 裁剪平面(osg::Scissor)示例(二)的代码如程序清单8-2所示 // 裁剪平面测试&#xff08;2&#xff09; void scissor_8_2(const string strDataFolder) { osg::ref_ptr<osgViewer::Viewer> viewer new osgViewer::Viewer(); osg::ref_ptr<osg::Gra…

原力CEO赵锐:ToDesk是国内唯一适合高精远程办公需求的解决方案

随着数字办公在各行业的渗透&#xff0c;远程办公也逐渐成为一种常态。2000多名艺术家员工遍布全球各地的江苏原力数字科技股份有限公司&#xff08;下称&#xff1a;原力&#xff09;&#xff0c;是一家国内业务范围、规模均遥遥领先的数字业务内容提供商。一直以来&#xff0…

在webstorm中配置sass编译环境

1.下载ruby 下载地址&#xff1a;ruby下载 2.安装ruby 下载之后&#xff0c;有一个exe安装包 双击exe文件 &#xff0c;并选择自己的安装位置&#xff08;这个位置一定要记得&#xff0c;需要在webstorm中使用&#xff09;。其他的步骤默认安装即可。 3.安装sass ruby安装成功后…

【MATLAB源码-第75期】基于模拟退火算法(SA)的栅格路径规划,输出做短路径图和适应度曲线。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 模拟退火算法是一种启发式优化算法&#xff0c;通常用于解决组合优化问题&#xff0c;例如旅行商问题和图着色问题。它模拟了固体材料在退火过程中逐渐冷却达到稳定状态的行为&#xff0c;以寻找问题的全局最优解。 以下是模…

故障演练的关键要素及重要性

故障演练是一种有计划的、模拟真实生产环境故障的活动。通过故意引入故障、模拟系统组件失效或模拟其他异常条件&#xff0c;团队可以观察并评估系统在这些情况下的反应。这有助于发现潜在的问题、改进应急响应和提高系统整体的可用性。 一、故障演练的关键要素 计划性&#xf…

异常--Java

cry…catch使用 /*需求&#xff1a;测试除法器&#xff08;try...catch&#xff09;* 测试人&#xff1a;小王* 测试日期&#xff1a;2023/11/15* */ package yichang_test1;import java.util.InputMismatchException; import java.util.Scanner;public class TestException2 …

【ROS导航Navigation】四 | SLAM与导航 | 自主移动的地图构建 (更新ing)

致谢&#xff1a;ROS赵虚左老师 Introduction Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程 参考赵虚左老师的实战教程 实现比较简单&#xff0c;步骤如下: 编写launch文件&#xff0c;集成SLAM与move_base相关节点&#xff1b;执行launch文件并测试。 <la…

无人机内存卡数据恢复

1.插入内存卡 2.选择对应的品牌 3.点击恢复 建议&#xff1a;发现数据打不开或者丢失情况&#xff0c;建议及时断电&#xff0c;以免影响数据的正常恢复&#xff01; #无人机##数据恢复##储存卡#