18.多线程基础
2021/6/6 10:50:57
本文主要是介绍18.多线程基础,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
@一贤爱吃土豆
1.进程
- 是系统进行资源分配调用的基本单位,每个进程都有自己独立的内存空间和系统资源.
- (正在运行的程序)
cpu时间片:指系统资源和内存空间.
2.线程
- 是进程中一条执行线路.每个线程都要执行一个任务.
- 线程是CPU的基本调度单位.
3.进程与线程的关系
- 一个进程可以有1个到多个线程.
- 一个线程永远只属于一个进程.
- 一个进程中多个线程之间是互抢资源的竟争关系.
4.实现线程
- 有三种实现线程的方式,前两种常用,第三周基本不用.
4.1:继承Thread方式实现线程
eg:/** * 线程子类 * @author sx * @version 1.0 2020年10月28日 */ public class MyThread extends Thread{ /** * 重写父类中任务方法 */ @Override public void run() { for (int i = 1; i <= 10; i++) { System.out.println(Thread.currentThread().getName()+":"+i); } } } public static void main(String[] args) { //创建子线程对象 MyThread t1=new MyThread(); MyThread t2=new MyThread(); //启动线程 t1.start(); t2.start(); }
4.2:实现Runnable接口的方式实现线程
eg:/** * 任务类 * @author sx * @version 1.0 2020年10月28日 */ public class MyRunnable implements Runnable{ /** * 重写父接口中任务方法 */ @Override public void run() { for (int i = 1; i <=10; i++) { System.out.println(Thread.currentThread().getName()+":"+i); } } } public static void main(String[] args) { //创建任务对象 MyRunnable m1=new MyRunnable(); MyRunnable m2=new MyRunnable(); //创建线程对象 Thread t1=new Thread(m1); Thread t2=new Thread(m2); //启动线程 t1.start(); t2.start(); }
4.3:实现Callable接口的方式实现线程
- (了解,现在基本不用).
5.继承Thread VS 实现Runnable接口的方式实现多线程
5.1:代码简洁性
- 继承Thread方式实现线程代码更简洁;
- 实现Runnable接口的方式实现多线程较复杂.
5.2:扩展性
- 继承Thread方式实现线程,这个类无法再继承其他类,只能实现其他接口,扩展性较差;
- 实现Runnable接口的方式实现线程,这个类还可以再继承其他的类,实现其他的接口,所以扩展性较好.
5.3:资源共享性
- 继承Thread方式实现多个线程,如果这多个线程想要执行同一个任务,那这个任务得定为静态才能实现共享,可是静态耗资源,所以共享性不好.
- 实现Runnable接口的方式实现多个线程,如果这多个线程想要执行同一个任务,只需要给这多个线程传递同一个任务对象,所以共享性好.
6.给线程取名:
6.1:每个线程都有默认名字.
6.2:用构造方法给线程取名.
eg:/** * 线程子类 * @author sx * @version 1.0 2020年10月28日 */ public class MyThread extends Thread{ /** * 有参构造,给线程取名 * @param string */ public MyThread(String name) { super(name); } /** * 重写父类中任务方法 */ @Override public void run() { for (int i = 1; i <= 10; i++) { System.out.println(Thread.currentThread().getName()+":"+i); } } }
6.3:在线程子类声明一个属性专门用来存线程名称.
6.4:调用线程对象setName(“名称”)
7.线程休眠
- 让当前的线程让出资源,停止对资源的抢夺,暂停指定时间,等时间到了,重新参与资源的抢夺.
- 语法:Thread.sleep(毫秒数); 或 线程对象名.sleep(毫秒数);
eg:public static void main(String[] args) throws InterruptedException { for (int i = 6; i >=1; i--) { System.out.println(i); Thread.sleep(1000); } }
8.线程优先级
- 线程优先级越高抢占资源的概率越高到,不一定能抢;线程优先级越低抢占资源的概 率越低,但不一定抢不到.
- 注意:线程优先级一定要在线程启动之前设置才有效.
- 语法:线程对象名.setPriority(int newPriority);
eg:public static void main(String[] args) { //创建线程对象 MyThread t1=new MyThread(); MyThread t2=new MyThread(); //给线程取名 t1.setName("线程A"); t2.setName("线程B"); //设置线程优先级 t1.setPriority(Thread.MIN_PRIORITY); t2.setPriority(Thread.MAX_PRIORITY); //启动线程 t1.start(); t2.start(); }
9.线程合并
- 将多个线程合并为一个线程,合并过来的线程先执行完,再执行原线程剩下部分.
- 语法:线程对象名.join();
9.1:让子线程合并主线程中:合并过来的子线程先运行完,再运行主线程剩下部分.
eg:public static void main(String[] args) throws InterruptedException { //创建子线程对象 Thread t1=new Thread(new Runnable() { /** * 重写父接口中任务方法 */ @Override public void run() { for (int i = 1; i <=100; i++) { System.out.println(Thread.currentThread().getName()+":"+i); } } }, "线程A"); //启动子线程对象 t1.start(); for (int i = 1; i <=100; i++) { System.out.println(Thread.currentThread().getName()+":"+i); //当主线程运行10时,让子线程A合并过来 if (i==10) { t1.join(); } } }
9.2:让子线程A合并子线程B中:合并过来的子线程A先运行完,再运行子线程B剩下部分.
eg:public class MyThread extends Thread{ //声明一个属性存线程对象 public MyThread t; /** * 任务方法 */ @Override public void run() { for (int i = 1; i <=100; i++) { System.out.println(Thread.currentThread().getName()+":"+i); //当子线程B运行10时,让子线程A合并过来 if (i==10&&Thread.currentThread().getName().equals("线程B")) { try { //this指代线程B对象 this.t.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } public static void main(String[] args) throws InterruptedException { //创建线程对象 MyThread tA=new MyThread(); MyThread tB=new MyThread(); //给线程取名 tA.setName("线程A"); tB.setName("线程B"); //给对象的属性赋值,让线程A作为线程B对象的一个属性 tB.t=tA; tA.t=null; //启动线程 tA.start(); tB.start(); }
10.线程礼让:让当前的线程让出资源,重新抢夺.
- 语法:Thread.yield(); 或者 线程对象.yield();
eg:public static void main(String[] args) { //创建线程对象 Thread ta=new Thread(new Runnable() { /** * 重写父接口中任务方法 */ @Override public void run() { for (int i = 1; i <=100; i++) { System.out.println(Thread.currentThread().getName()+":"+i); } } }, "线程A"); //启动线程 ta.start(); for (int i = 1; i <=100; i++) { System.out.println(Thread.currentThread().getName()+":"+i); //主线程每运行一次就礼让一次 Thread.yield(); } }
11.线程中断
11.1:用中断方法
- interrupt()改变线程的中断状态,
- isInterrupted()判断线程的状态是否中断.
eg:public static void main(String[] args) throws InterruptedException { //创建线程对象 Thread ta=new Thread(new Runnable() { /** * 重写父接口中任务方法 */ @Override public void run() { for (int i = 1; i <=100; i++) { //判断当前的线程中断状态是否为true if (Thread.currentThread().isInterrupted()==true) { break; } System.out.println(Thread.currentThread().getName()+":"+i); } } }, "线程A"); //启动线程 ta.start(); for (int i = 1; i <=100; i++) { System.out.println(Thread.currentThread().getName()+":"+i); //当主线程运行10时,中断子线程A的执行 if (i==10) { //改变子线程当前中断状态 ta.interrupt(); //主线程休眠将资源让出来,这样子线程的中断才会生效 Thread.sleep(2000); } } }
11.2:用一个变量作标记,标记线程是否需要中断
eg:public class InterruptTest2 { //声明一个变量作标记,标记子线程是否中断,默认不中断 static boolean flag=false; public static void main(String[] args) throws InterruptedException { //创建线程对象 Thread ta=new Thread(new Runnable() { /** * 重写父接口中任务方法 */ @Override public void run() { for (int i = 1; i <=100; i++) { //判断当前的线程中断标记是否为true if (flag) { break; } System.out.println(Thread.currentThread().getName()+":"+i); } } }, "线程A"); //启动线程 ta.start(); for (int i = 1; i <=100; i++) { System.out.println(Thread.currentThread().getName()+":"+i); //当主线程运行10时,中断子线程A的执行 if (i==10) { //改变中断标记 flag=true; //让主线休眠,这样子线程就能抢到资源运行生效 Thread.sleep(1000); } } } }
12.守护线程(后台线程,精灵线程)
- 守护线程守护所有非守护线程,当一个进程中所有的非守护线程死亡了,守护线程自动死亡.
- 注意:设置线程为守护线程时,一定要在启动线程之前设置才有效.
- 语法:线程对象.setDaemon(true);
eg:public static void main(String[] args) { //创建线程对象 Thread t1=new Thread(new Runnable() { /** * 重写父接口中任务方法 */ @Override public void run() { for (int i = 1; i <=1000; i++) { System.out.println(Thread.currentThread().getName()+":"+i); } } }, "守护线程"); //设置子线程为守护线程 t1.setDaemon(true); //启动线程 t1.start(); for (int i = 1; i <=10; i++) { System.out.println(Thread.currentThread().getName()+":"+i); } }
13.线程生命周期:(面试经典)
13.1:初始状态(新建状态)
- 当一个线程对象刚被new(创建)出来时,这个线程对象就处于初始状态.
13.2:就绪状态
- 当一个线程对象调用start(),或阻塞(sleep(),wait())的线程本来后就处于就绪状态.
13.3:运行状态
- 当就绪状态的线程抢到cpu时间片,调用run()时,这时线程就处于运行状态.
13.4: 阻塞状态
*当一个线程调用sleep()或wait()时,这个线程就处于阻塞状态.
13.5:终止状态(死亡状态)
- 当一个线程不能再执行时(任务执行完或被中断),这个线程就等于终止状态.
总结:
1.了解HashTable和Properties
2.集合的总结(重点)
3.异常定义及分类
4.异常的处理机制(try-catch-finally和throws)(重点)
5.自定义异常
6.进程和线程的定义及区别(重点)
7.实现线程的两种方式(重点)
8.给线程取名
9.继承Thread VS 实现Runnable接口的方式实现多线程(重点)
10.实现线程的第三种方式(了解)
11.线程休眠(重点)
12.线程优先级(了解)
13.线程合并(重点)
14.线程礼让(了解)
15.线程中断(重点)
16.守护线程
17.线程生命周期(重点)
18.线程池(重点)
这篇关于18.多线程基础的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-10-06小米11i印度快充版ROM合集:极致体验,超越期待
- 2024-10-06【ROM下载】小米11i 5G 印度版系统, 疾速跃迁,定义新速度
- 2024-10-06【ROM下载】小米 11 青春活力版,青春无极限,活力全开
- 2024-10-05小米13T Pro系统合集:性能与摄影的极致融合,值得你升级的系统ROM
- 2024-10-01基于Python+Vue开发的医院门诊预约挂号系统
- 2024-10-01基于Python+Vue开发的旅游景区管理系统
- 2024-10-01RestfulAPI入门指南:打造简单易懂的API接口
- 2024-10-01初学者指南:了解和使用Server Action
- 2024-10-01Server Component入门指南:搭建与配置详解
- 2024-10-01React 中使用 useRequest 实现数据请求