多线程实现
多线程实现对比
Java多线程启动
·启动
- start方法,会自动以新进程调用run方法(并行运行(多线程运行))
- 直接调用run方法,将变成串行执行
- 同一个线程,多次start会报错,只执行第一次start方法
- 多个线程启动,其启动的先后顺序是随机的
- 线程无需关闭,只要其run方法执行结束后,自动关闭
- main函数(线程)可能早于新线程结束,整个程序并不终止
- 整个程序终止是等所有的线程都终止(包括main函数线程)
Thread vs Runnable
-Thread占据了父类的名额,不如Runnable方便
-Thread类实现Runnable
-Runnable启动时需要Thread类的支持
-Runnable更容易实现多线程中资源共享
结论:建议实现Runnable接口来完成多线程
多线程信息共享
-static变量(不同线程之间操作变量时不可见)
-同一个Runnable类的成员变量
-采用volatile关键字修饰变量(保证不同线程对共享变量操作时的可见性)
关键步骤加锁限制
一互斥:某一个线程运行一个代码段(关键区),其他线程不能同时运行这个代码段
一同步:多个线程的运行,必须按照某一种规定的先后顺序来运行
一互斥是同步的一种特例
互斥的关键字是synchronized
-synchronized代码块/函数,只能一个线程进入
-synchronized加大性能负担,但是使用简便
线程状态
-创建(new)
-就绪(start)
-运行(run)
-阻塞(sleep)
-结束
线程阻塞/和唤醒
- sleep,时间一到,自己会醒来
- wait/ notify/notifyAll,等待,需要别人来唤醒
- join,等待另外一个线程结束
- interrupt,向另外一个线程发送中断信号,该线程收到信号,会触发InterruptedException(可解除阻塞),并进行下一步处理
生产者和消费者问题
多线程死锁
-每个线程互相持有别人需要的锁(哲学家吃面问题)
-预防死锁,对资源进行等级排序
守护(后台)线程(setDaemon(true))
-普通线程的结束,是run方法运行结束
-守护线程的结束,是run方法运行结束,或main函数结束
-守护线程永远不要访问资源,如文件或数据库等
·线程查看工具jvisualvm
并行计算
线程组管理ThreadGroup
—线程的集合
—树形结构,大线程组可以包括小线程组
—可以通过enumerate方法遍历组内的线程,执行操作
—能够有效管理多个线程,但是管理效率低
—任务分配和执行过程高度耦合
一重复创建线程、关闭线程操作,无法重用线程
Executor框架
Executor FrameWork (java.util.concurrent.*)
一分离任务的创建和执行者的创建
一线程重复利用(new线程代价很大)·理解共享线程池的概念
一预设好的多个Thread,可弹性增加一多次执行很多很小的任务
一任务创建和执行过程解耦
一程序员无需关心线程池执行任务过程
主要类:ExecutorService, ThreadPoolExecutor,Future
—Executors.newCachedThreadPool/ newFixedThreadPool创建线程池
—ExecutorService线程池服务
—Callable具体的逻辑对象(线程类)
— Future返回结果