当前位置: 首页 > news >正文

多线程的基础知识以及应用

一、什么是多线程

1.1、什么是进程

进程我们可以理解为程序的基本执行实体,我们打开任务管理器,每个软件的运行就是1个进程

1.2、多线程

         线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位

        例如我们打开360软件,360软件本身就是1个进程,360里面的木马查杀电脑清理系统修复优化加速等功能就是多个线程

 总结:

多线程就是应用软件中相互独立,可以同时运行的功能

二、创建线程的三种方式

2.1、继承thread类重写run方法 

​
package cn.itcast.thread;public class MyThread extends Thread{@Overridepublic void run() {for (int i = 0; i <100 ; i++) {String name = getName();System.out.println("我是:" + name);}}
}​

然后在main方法中执行,如果在test方法中执行,可能出现线程执行时间过短,无法展示完整的结果

package cn.itcast.thread;import org.junit.Test;import java.util.Calendar;
import java.util.Date;public class Test1 {//@Test//public void test1() {//    MyThread myThread1=new MyThread();//    myThread1.setName("线程1");//    myThread1.start();//    MyThread myThread2=new MyThread();//    myThread2.setName("线程2");//    myThread2.start();////}public static void main(String[] args) {MyThread myThread1=new MyThread();myThread1.setName("线程1");myThread1.start();MyThread myThread2=new MyThread();myThread2.setName("线程2");myThread2.start();}}

2.2、实现Runnable接口,重写run方法

package cn.itcast.thread.run;public class MyRun implements Runnable{@Overridepublic void run() {for (int i = 0; i < 100; i++) {Thread thread = Thread.currentThread();System.out.println("我是:"+thread.getName());}}
}

然后在main方法中执行

package cn.itcast.thread.run;import cn.itcast.thread.MyThread;
import org.junit.Test;public class Test1 {//@Test//public void test1() {//    //要执行的线程任务//    MyRun myRun=new MyRun();//    //创建线程对象//    Thread t1=new Thread(myRun);//    t1.setName("线程1");//    Thread t2=new Thread(myRun);//    t2.setName("线程2");//    //开启线程//    t1.start();//    t2.start();////}public static void main(String[] args) {//要执行的线程任务MyRun myRun=new MyRun();//创建线程对象Thread t1=new Thread(myRun);t1.setName("线程1");Thread t2=new Thread(myRun);t2.setName("线程2");//开启线程t1.start();t2.start();}}

2.3、实现Callable接口重写call方法

package cn.itcast.thread.call;import java.util.concurrent.Callable;public class MyCall implements Callable<Integer> {@Overridepublic Integer call() throws Exception {Integer sum=0;for (int i = 0; i <=100; i++) {sum=sum+i;}return sum;}
}

然后在main方法中执行

package cn.itcast.thread.call;import cn.itcast.thread.run.MyRun;
import org.junit.Test;import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;public class Test1 {//@Test//public void test1() throws ExecutionException, InterruptedException {//    //要执行的线程任务//    MyCall myCall=new MyCall();//    //FutureTask对象用来管理多线程运行的结果//    FutureTask<Integer>futureTask=new FutureTask<>(myCall);//    //创建线程对象//    Thread t1=new Thread(futureTask);//    //开启线程//    t1.start();//    //拿到多线程的运行结果//    Integer result = futureTask.get();//    System.out.println(result);////}public static void main(String[] args) throws ExecutionException, InterruptedException {//要执行的线程任务MyCall myCall=new MyCall();//FutureTask对象用来管理多线程运行的结果FutureTask<Integer>futureTask=new FutureTask<>(myCall);//创建线程对象Thread t1=new Thread(futureTask);//开启线程t1.start();//拿到多线程的运行结果Integer result = futureTask.get();System.out.println(result);}}

三种方法具体的差别,以及thread类的常用API看之前写的文章

并发和并行的概念也看之前的文章

JAVA基础进阶(十一)-CSDN博客

三、守护线程

 守护线程指的是非守护线程全部结束后,守护线程一定结束

创建线程1

package cn.itcast.thread.protect;public class MyThread1 extends Thread{@Overridepublic void run() {for (int i = 0; i <10 ; i++) {String name = getName();System.out.println(name + "@"+i);}}
}

创建线程2

package cn.itcast.thread.protect;public class MyThread2 extends Thread{@Overridepublic void run() {for (int i = 0; i <100 ; i++) {String name = getName();System.out.println(name + "@"+i);}}
}

在main方法中将MyThread2线程设置为守护线程:myThread2.setDaemon(true);

package cn.itcast.thread.protect;import cn.itcast.thread.MyThread;
import org.junit.Test;public class Test1 {//@Test//public void test1() {//    MyThread1 myThread1=new MyThread1();//    myThread1.setName("女神");//    MyThread2 myThread2=new MyThread2();//    myThread2.setName("备胎");//    myThread2.setDaemon(true);//    myThread1.start();//    myThread2.start();//}public static void main(String[] args) {MyThread1 myThread1=new MyThread1();myThread1.setName("女神");MyThread2 myThread2=new MyThread2();myThread2.setName("备胎");myThread2.setDaemon(true);myThread1.start();myThread2.start();}}

得到最终结果:

 当非守护线程myThread1结束后,守护线程myThread2执行一段时间后会立马结束,不会执行完,myThread2执行完最后应该是99,只执行到了11

应用场景:打开qq聊天,同时传输文件,qq聊天就相当于非守护线程,传输文件就相当于守护线程,当关闭聊天框,传输文件也会随之关闭

四、线程的生命周期

4.1、创建线程

1、使用start()方法创建线程后,线程就处于就绪状态,此时线程有执行资格,但是没有执行权,因为需要和其他的线程不停抢占CPU的执行权

2、当抢到CPU的执行权后,此时线程既有执行资格又有执行权,就能执行线程中的代码,此时线程处于运行状态

3、如果此时CPU的执行权被其他线程抢走,线程就又会回到就绪状态,又或者线程被sleep()方法或者其他方法阻塞,就既没有执行资格也没有执行权,处于阻塞状态,如果以上两种情况都没有出现,那么线程就能执行完毕,线程就会死亡变成垃圾。

 

五、线程安全问题

相关文章:

  • 计算机视觉---YOLOv2
  • 2021年认证杯SPSSPRO杯数学建模B题(第二阶段)依巴谷星表中的毕星团求解全过程文档及程序
  • 计算机网络学习(六)——UDP
  • Go语言Map的底层原理
  • mysql都有哪些锁?
  • Java并发编程:全面解析锁策略、CAS与synchronized优化机制
  • 基于SpringBoot的校园电竞赛事系统
  • uni-app学习笔记十二-vue3中组件传值(属性传值)
  • Redis之金字塔模型分层架构
  • [医学影像 AI] 使用 PyTorch 和 MedicalZooPytorch 实现 3D 医学影像分割
  • Linux Kernel调试:强大的printk(二)
  • 两个mysql的maven依赖要用哪个?
  • 高级特性实战:死信队列、延迟队列与优先级队列(一)
  • 基于MATLAB编程针对NCV检测数据去漂移任务的完整解决方案
  • [特殊字符] Function Calling 技术详解与 Qwen 模型实践指南
  • 软考 系统架构设计师系列知识点之杂项集萃(72)
  • Oracle控制文件损坏恢复方案
  • RabbitMQ 可靠性保障:消息确认与持久化机制(一)
  • Android应用中设置非系统默认语言(使用Kotlin)
  • ChatGPT+知网,AI如何辅助真实科研写作流程?
  • 网站建设公司如何发展/好用的搜索引擎有哪些
  • linux操作怎么做网站/淘宝店铺如何推广
  • 网站设计的公司设计/关键词查网址
  • 上海做网站优化价格/宁波seo网络推广代理公司
  • 辽宁模板网站建设公司/湖南正规seo优化
  • 做百度网站还是安居客网站/百度推广找谁做靠谱