1.什么是多线程
多线程就是多条线程同时工作,或者交替工作
1.1.线程与进程:
线程(Thread):线程是进程中最小的调度的单元(单位),cpu控制的最小的执行单元。轻量级的进程。任何一个程序都至少有一个线程在用,多个线程共享内存。多线程切换消耗的资源少。
进程(Processor):活动的程序,进程;已经启动,进驻到内存中,正在使用的程序,:进程;每个进程拥有独立的内存空间。
线程与进程的关系:通俗来说进程就是一个软件,而线程就是 该软件运行时的最小的执行单位,例如某一条信息的发送,接到别人拨打的电话。
1.2.并发与并行:
并发:在同一个时间段内,多个线程交替进行
并行:在同一个时刻,多个线程同时进行
*单个cpu的主机只能同时进行一个线程*
2.怎么创建线程
2.1
1.继承Thread类:
重写run方法=>创建线程对象=>启动线程
*继承简单,但受限与Java的单继承的影响,不常用
2.实现Runnable接口
先实现Runnable接口,再重写run方法
*继承类,实现多个接口,实现资源的共享,常用
3.实现Callable接口
实现Callable接口
*可以获取线程的返回值
2.2Thread类中常用的方法
方法 | 描述 | ||
public static Thread currentThread() | 返回当前的线程 | ||
public final String getName() | 返回线程名称 | ||
public final void setPriority(int priority) | 设置线程优先级 | ||
public void start() | 开始执行线程 | ||
public static void sleep(long m) | 使目前的线程休眠(s,m,d) | ||
public final void yield() | 暂停目前的线程,运行其他 线程 | ||
public void run() | 线程要执行的任务 |
2.3线程的调度(线程的级别)
线程有三种级别:
线程的优先级别用整数来区别最低1,而最高是10
线程的级别是可以设置的
设置最高级 static int MAX_PRIORITY
设置默认级 static int NORM_PRIORITY
设置最低级 static int MIN_PRIORITY
优先级别越高,抢到时间片的概率越大,越有可能运行该线程(注:级别越高并不是先运行,而是抢到时间片的概率越大)
3.线程的状态
3.1.线程的状态分为五种
1、新建状态(New):新创建了一个线程对象。
2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
3、运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。
5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期
3.什么是线程同步
3.1线程同步
当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作,其他线程才能对该内存地址进行操作
那相对的线程异步处理就不用阻塞当前线程,而是允许后续操作,直至其他线程将处理完成,并回调此线程
线程同步的利弊
-
好处:解决了线程同步的数据安全问题
-
弊端:当线程很多的时候,每个线程都会去判断同步上面的这个锁,很耗费资源,降低效率
3.2实现同步的方式
1、基于synchornized(同步)实现
2、基于Lock实现
3.3synchronized与Lock的对比
Lock是显示锁,需要自己手动开启和关闭,synchronized是隐式锁,出了作用于自动释放,无需自己释放。
Lock只能锁代码块,synchronized可以锁代码块和方法
使用Lock锁,JVM将花费更少的时间来调度线程,性能更好。并且具有更好的扩展性(提供更多的子类)
4.死锁
4.1死锁是什么
死锁:当多个线程各自占有一些共享资源,并且互相等待其他线程占有的资源才能进行,从而导致两个或者多个线程都在等待对方释放资源,都停止执行的情况。
最简单的死锁是:某一个同步块同时拥有“两个以上的对象的锁”的时候,就可能会发生死锁问题。
4.2如何避免死锁
1.尽量避免使用多个锁(如果有可能的话)。
2.规范的使用多个锁,并设计好锁的获取顺序。
3.随用随放。即是,手里有锁,如果还要获得别的锁,必须释放全部资源才能各取所需。
4.规范好循环等待条件。比如,使用超时循环等待,提高程序可控性。
***本文章仅用于学习时的周末总结***