工作中需要用到的Java知识(多线程篇)
多线程是Java中很重要的一个内容,现在的项目大多都追求高并发,这个高并发就需要用到多线程。
先解释一下什么是线程。
解释什么是线程,我先引入两个概念,一个是程序,一个是进程。他们的关系是:
每个线程都有独立的虚拟机栈,但是他们会 共享方法区与堆空间 ,这会使得线程间通信更加简便高效,但是同时也会带来安全的隐患,这里就是我们之前说过的线程安全与线程不安全。
线程安全的,就说明多线程时,不会带来隐患。
线程不安全的,说明多线程时,可能会有隐患。
单核CPU与多核CPU的理解
单核CPU中的多线程就好像只有一个人在工作,他可以身兼数职,做所有的工作,因为执行的时间很短,我们察觉不出来,在单核CPU中进行多线程,可能耗时会比正常顺序执行更慢,因为CPU需要在线程之间切换,但是有时候还是需要用到多线程,比如下载的时候,我们可能希望下载的时候同时下载五六个文件,点击下载后,我们就不需要管了,这时候多线程就可以完成这个任务,不然我们需要下载完一个再点击下载第二个,用户的体验就会极差。
多核CPU中的多线程就好像多个人在工作,压力小了,速度也会更快。
并行与并发的理解
并行:多个CPU执行多个任务。
并发:一个CPU执行多个任务,就类似于ajax异步传输,可以同时进行多种工作。
多线程的创建及使用
在Java语言中多线程通过java.lang.Thread类来体现。
操作为将需要执行的方法放到run()方法内,然后通过start()方法来启动此线程。
多线程有两种创建方式。
一 继承Thread类
1.创建一个继承Thread类的子类
2.重写Thread类的run()方法
3.创建Thread类子类的对象
4.通过子类对象调用start()方法
run()方法中为要执行的逻辑内容,而start()方法相当于启动器开关,如果想要启动线程,就一定要调用start()方法。
二 实现Runnable接口
1.创建一个实现Runnable类的类
2.实现Runnable接口中的抽象方法—>run()
3.创建实现类的对象
4.将此对象作为参数放入Thread类的构造器中,创建Thread对象
5.通过Thread对象调用start()方法
两者的优缺点:
Thread类创建多线程的优先是方式简单,缺点就是Java的特性为单继承,可能我们在工作中还需要继承其他的类,所以确定父类对象需要谨慎,能用接口就用接口实现,反之,Runnable接口实现多线程的优点就是不需要继承,缺点就是方式相比继承Thread类复杂。
Thread类多个线程如果想要共享一个变量,需要将其变为静态变量,而Runnable接口则不需要,只需要在创建Thread类的时候,构造器参数传入同一个对象即可。
开发中优先使用Runnable接口的创建多线程方式。
多线程中常用方法
方法名 | 作用 |
---|---|
run | 用来设置执行哪些逻辑的一个主体,多线程启动时,主要就是用来执行此方法 |
start | 用来启动多线程,相当于多线程的一个开关方法 |
setName | 设置多线程的名字 |
getName | 获得多线程的名字 |
currentThread | 返回当前线程,执行到此方法处在谁的线程下,就会返回谁的线程对象 |
yield | 释放执行权,自己主动停止的方法,仅停止一次,有可能CPU继续分给其对象执行权 |
join | 在线程A中调用B的join方法,此时A进入阻塞状态,只有B执行完毕,A才会继续执行(会抛出异常) |
sleep | 睡眠,线程会让出执行权休息一会,但是不会让出锁(会抛出异常)睡眠时间到了,会继续执行 |
wait | 等待,调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备 |
isAlive | 判断当前线程是否存活 |
getPriority | 返回当前线程的优先级 |
setPriority | 改变当前线程的优先级 |
isAlive | 判断当前线程是否存活 |
isAlive | 判断当前线程是否存活 |
线程的优先级
优先级最大MAX_PRIORITY = 10
优先级最小MIN_PRIORITY = 1
默认优先级NORM_PRIORITY = 5
修改优先级只是有可能优先执行,并不是绝对的
这就是基础的多线程内容了,进阶版看这里↓
工作中需要用到的Java知识(多线程进阶篇)