定义
多线程(multithreading),是指从软件或者硬件上实现多个线程并发执行的技术。
相关定义
1:并发和并行
(1):并发:指两个或多个事件在同一个时间段内发生。
(2):并行:指两个或多个事件在同一时刻发生(同时发生)。
在单 CPU 系统中,每一时刻只能有一道程序执行,即微观上这些程序是分时的交替运行,只不过是给人的感觉是同时运行,那是因为分时交替运行的时间是非常短的。
在多个 CPU 系统中,则这些可以并发执行的程序便可以分配到多个处理器上(CPU),实现多任务并行执行,即利用每个处理器来处理一个可以并发执行的程序,这样多个程序便可以同时执行。目前电脑市场上说的多核CPU,便是多核处理器,核越多,并行处理的程序越多,能大大的提高电脑运行的效率。
2:线程和进程
(1):进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创建、运行到消亡的过程。
角度一
一个应用程序,启动多个处理进程。换言之,所有进程隶属于当前应用程序;这是所谓的多进程服务。
角度二
启动多个同一应用程序,每个应用程序都是单进程。这个场景有些应用程序会禁用掉,有些是可以的,看应用程序的定位。如果允许,那么需要解决数据共享的问题(主要是数据写入);如果不允许,那么只能启动一个此类应用程序。
设置进程优先级
JAVA多进程,一般听说很少,这里不展开,以后再补充。
(2):线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。
简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程
3:线程调度
(1):分时调度:所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间。
(2):抢占时调度: 优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度。
多线程程序并不能提高程序的运行速度,但能够提高程序运行效率,让CPU的使用率更高。
创建多线程
方法一:继承Thread类
public static void main(String[] args) {
new Thread() {
@Override
public void run() {
System.out.println("继承Thread类实现多线程");
}
}.start();
}
//结果:
继承Thread类实现多线程
方法二:实现Runnable接口
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("实现Runnable接口,重写run方法,实现多线程");
}
}).start();
//结果:
实现Runnable接口,重写run方法,实现多线程
注意: 直接实现Runnable接口,没有返回值,若创建FutureTask对象:new FutureTask(Callable
方法二的优势:
1.适合多个相同的程序代码的线程去共享同一个资源。
2.可以避免java中的单继承的局限性。
3.增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和线程独立。
4.线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类。
扩充:在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个JVM其实在就是在操作系统中启动了一个进程。
线程安全问题
定义:
当我们使用多个线程访问同一资源的时候,且多个线程中对资源有写的操作,就容易出现线程安全问题。
解决线程安全问题方案:
方法一:
使用同步代码块
public void safe(){
//this 这里放要锁的对象,多个线程之间该对象必须一致
synchronized (this){
//需要同步操作的代码
System.out.println("这是代码块锁");
}
}
方法二:
使用同步方法
public synchronized void safe(){
//对于非static方法,同步锁就是this
//对于static方法,我们使用当前方法所在类的字节码对象(类名.class)
//需要同步操作的代码
System.out.println("这是代码块锁");
}
方法三:
Lock锁
public void lockDemo(){
//ReentrantLock为可重入锁
Lock lock=new ReentrantLock();
//加锁
lock.lock();
System.out.println("Lock锁示列");
//释放锁
lock.unlock();
}
线程状态
定义:
当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态。
在API中java.lang.Thread.State这个枚举中给出了六种线程状态
状态:
六种状态: