多线程的优势与风险
优势:
- 速度快:同时处理多个任务,可充分利用处理器的资源提高系统吞吐率,响应更快。
- 设计简化:复杂的任务可以分多个小任务执行完成,简化程序建模设计
- 资源利用高:异步充分利用资源,使cpu可以在等待其他资源时(如等待io)处理其他的任务
风险:
- 安全性:多线程共享变量,可能会产生不相符的结果
- 活跃性:某个操作由于等待其他资源无法进行下去,如死锁、饥饿等。
- 性能:cpu频繁切换、调度时间增加、同步机制消耗过多内存等
所以多线程使用不当,不仅系统得不到优化的提升,反而产生一些病态的行为,如死锁、竞争、活锁(任务未阻塞,但某些条件不满足一直尝试失败)、饿死【饥饿】(资源一直被其他线程占有,如打印机),数据不一致等问题。
并发模拟工具
1、Postman 图形化操作、
2、Apache beach命令:ab -n 1000 -c 50 url (-n 1000为请求总数, -c 50为并发总数)
3、JMeter
创建线程的方式
- 继承Thread类,重写run()方法
- 实现Runnable接口,并作为参数构造Thread类
线程启动Thread.start()。
Thread类的常用方法:
方法 | 描述 |
---|---|
static Thread currentThread() | 返回对当前正在执行的线程对象的引用 |
static void yield() | 让步,可能让出cpu调度器的时间片后,在第一时间又抢到了 |
static void sleep(long) | 休眠,此操作受到系统计时器和调度程序精度和准确性的影响 |
long getId() | 标识符唯一ID |
String getName() | 线程名称 |
void setName(String) | 设置线程名称 |
int getPriority() | 返回线程的优先级 |
void setPriority(int) | 设置线程优先级 |
boolean isDaemon() | 是否为后台(守护)线程 |
void setDaemon(boolean) | 设置后台(守护)线程 |
void interrupt() | 中断线程 |
boolean interrupted() | 是否中断状态 ,标记位状态将复位(清理) |
boolean isInterrupted() | 是否中断状态 |
boolean isAlive() | 线程存活状态 |
void join() | 加入一个线程 |
void join(long millis) | 指定时间内,加入一个线程 |
void start() | 启动线程 |
后台线程服务于主线程,所以主线程结束,后台线程也会跟随着结束,如java垃圾回收是后台线程,有后台线程创建的子线程也会是后台线程,void setDaemon(boolean)必须在start()方法启动线程之前设置才会生效。
未捕获的异常
继承错误的代价由别人来承担,而承认错误的代价由自己承担
static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh)
void setUncaughtExceptionHandler(UncaughtExceptionHandler eh)
专属的异常捕获优先默认的。默认未捕获的异常输出SSystem.err中
线程状态有六种,定义在Thread.State中
- 新建状态NEW:线程尚未启动,或正在分配必要的系统资源时。当线程所需资源分配完成,有资格获取cpu时间片,调度器将该线程转为RUNNABLE状态
- 可运行状态(就绪)RUNNABLE:此刻只要调度器把时间片分配给该线程,线程就可以运行,不分配时间片不运行,但不是阻塞
- 同步阻塞BLOCKED:线程正在等待监视器锁,以便进入一个同步的块/方法
- 条件阻塞WAITING :等待某个条件,如线程调用不带超时的Object.wait()、Thread.join()方法
- 超时等待TIMED_WAITING: 指定时间内等待某个条件,如Thread.join(long)、Threa.sleep(long)或io阻塞等
- 终止状态TERMINATED:线程死亡或终止(一般为run()方法结束或线程中断),线程将不会再被调度
BLOCKED、WAITING、TIMED_WAITING都可以为阻塞状态,此刻调度器会忽略线程,不会分配时间片,直到线程进入就绪RUNNABLE状态。
对象终结规则:finalize()方法结束
☀>.freerme、我是lilee[https://blog.csdn.net/freerme]