多线程(一)
什么是进程?
程序是静态的,进程就是程序的一次动态执行,当程序进入内存运行时既为进程
什么是线程?
是进程的组成单元,一个进程包含一个或多个线程,每一个线程负责单独执行一个单独的任务
线程与进程的区别?
- 一个进程包含多个进程
- 每个进程都有自己独立的内存空间,线程没有自己独立的内存空间,线程共享所在进程的内存空间
- 进程是重量级的单元,需要系统资源较多,线程是轻量级单元,需要的资源比较少
什么是多进程?
多进程是操作系统可以同时运行多个进程,一个CPU内核一个时间只能执行一个进程,CPU会在多个进程之间来回切换,因为速度特别的快,用户感觉不到。
什么是多线程?
多线程是一个进程里面有多个线程,CPU执行进程时会来回切换里面的所有的线程,每个线程会分配到一定的CPU执行时间(CPU时间片)
为什么要使用多线程?
- 充分利用CPU的性能
- 提升程序的运行效率
- 提升用户体验
多线程的应用场景?
来一个用户,新建一个线程,线程的资源是有限的
- 线程池
- 多路复用
多线程是不是一定比单线程快?
这个问题涉及到工作量的大小,如果工作量大,一定快;如果工作量小,不一定,因为线程的切换也需要时间。
什么是并行和并发?
并行:从线程角度来说,同一时刻,可以同时处理事情的能力(代码优化,分布式服务中,A服务需要多次调用B服务)。从CUP角度来说,多个CUP可以同时执行一个进程中的多个线程。
并发:从线程角度来说,在单位时间,可以处理事情的能力。从CUP角度来说,一个CUP在多个线程之间快速切换,达到同时执行多个任务的目的。
线程的生命周期?
创建,就绪,运行,阻塞,死亡
创建线程的三种方式?
- 继承Thread类
- 实现Runnable接口
- 实现Callable接口
继承Thread抽象类:
优点:编写简单,如果需要访问当前线程,无需使用Thread.currentThread()方法,直接this即可。
缺点:java是单继承的,无法再继承其他类。
MyThread.java
public class MyThread extends Thread{ //1.编写run方法 @Override public void run() { System.out.println("这个是自定义线程的方法体"+Thread.currentThread().getName()); } public static void main(String[] args) { //这里不是调用run方法,如果调用了run方法,就变成了普通的方法调用,没有起到多线程的效果 MyThread myThread1 = new MyThread(); MyThread myThread2 = new MyThread(); myThread1.start(); myThread2.start(); } }
运行截图:
实现Runnable接口:
点进Thread类中可以发现Thread类实现了Runnable接口。我们也可以通过实现Runnable接口来创建线程
MyRunnable.java
public class MyRunnable implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()+"实现runnable接口实现的"); } public static void main(String[] args) { Thread thread1 = new Thread(new MyRunnable()); Thread thread2 = new Thread(new MyRunnable()); thread1.start(); thread2.start(); } }
运行截图:
实现Callable接口:
Callable的任务执行后有返回值,通过get()可以拿到。FutureTask的线程执行的时候是异步的,获取结果的时候是同步的。
public class MyCallable implements Callable<Long> { @Override public Long call() throws Exception { return 1L; } public static void main(String[] args) throws ExecutionException, InterruptedException { FutureTask futureTask = new FutureTask(new MyCallable()); Thread thread = new Thread(futureTask); //启动 thread.start(); //获取值 Long aLong = (Long) futureTask.get(); System.out.println("aLong = " + aLong); } }
运行截图:
Runnable与Callable的区别?
Runnable规定的是run()方法,Callable规定的是call()
Runnable的任务执行完后无返回值,Callable的任务执行后有返回值
run()不能抛出异常,因为run()方法本身没有抛出异常,call可以
start()与run()的区别?
start()用来开启线程,但是线程开启后没有立即执行,在获取CPU的执行权后才可以执行
run()是由jvm创建完本地操作系统及线程后回调的方法,不可以手动调用。
什么是线程调度?
线程调度指按照特定机制为多个线程分配CPU的使用权。
线程调度的基本方式?
线程调度的基本方式有六个方法
void setPriority() 更改线程的优先级
void sleep() 线程休眠
void join() 线程终止(可设置等待时间)
void field() 礼让其他线程,次数,概率都是随机的
void interrupt() 中断线程,也是随机的
void isAlive() 测试线程是否处于活动状态
join()可以理解为插队,谁join就在之前执行,例如:有一个叫张三(主线程),李四插队lisi.join(),王五插队wangwu.join()。执行顺序wangwu - > lisi - > zhangsan
join例子:
MyRunnable.java接口
public class MyRunnable implements Runnable{ @Override public void run() { for (int i=0;i <20;i++){ System.out.println(Thread.currentThread().getName()+"实现runnable接口实现的"); } } }
join.java类
public class Join { public static void main(String[] args) { Thread thread = new Thread(new MyRunnable(), "线程A"); thread.start(); for (int i=0;i<100;i++){ if(i == 5){ try { Thread.currentThread().join(8); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("主线程" + i); } } }
当i等于5时,线程A执行join(),主线程等待8毫秒,A线程全部执行完
运行结果:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通