多线程
1. 实现多线程
1. 进程
- 是正在运行的程序
- 系统进行资源分配和调用的独立单位
- 每一个进程都有他自己的内存空间和系统资源
2. 线程
- 是进程中的单个顺序控制流,是一条执行路径
- 单线程
- 多线程
3. 线程生命周期
- 新建 —> 就绪 —> 运行 —> 死亡
- (<— 阻塞 <—)
4. 多线程的调用
方式1. 继承Thread类
- 定义一个MyThread 类,然后继承Thread类,重写run方法
- start(): 启动线程,然后由JVM调用此线程的run方法
5. 设置和获取线程名称
1. void setName(String name) //设置
2. void getName() //获取
//获取main()方法所在线程的名称: xxx.currentThread.getName();
public static currentThread(): //返回对当前正在执行的线程对象的引用
6. Thread中获取和设置线程优先级的方法
1. public final int getPriority() //返回线程优先级
2. public final void setPriority() //更改线程优先级
3. //默认是5,范围是1~10
7. 线程控制
1. static void sleep (long millis) //使当前执行的线程停留指定的毫秒数
2. void join() //等待这个线程的死亡
3. void setDaemon(boolean on) //将此线程标记为守护线程,当运行的线程是守护线程时,java虚拟机退出(也就是主线程结束,只剩下守护程序)
8. 多线程的实现方式
1. 两种实现方式
- 继承Thread类
- 实现Runnable接口
2. 实现Runnable接口
- 定义一个类实现Runnable接口
- 重写run()方法
- 创建类对象
- 以类对象为构造方法的参数 创建Thread类的对象
- 启动线程
3. 相比而言,实现Runnable接口的好处
- 避免了java单继承的局限性
- 适合多个相同程序的代码去处理 同一个资源的情况,把线程和程序的代码、数据有效分离,较好的体现了面向对象的设计思想
2. 线程同步
1. 线程执行的随机性导致问题
2. 同步代码块
格式:
synchronized(任意对象) {
多条语句操作共享数据的代码
}
synchronized(任意对象) : 就相当于给代码加上锁了,任意对象可以看成一把锁
同步的好处和弊端:
- 好处:解决了多线程的数据安全问题
- 坏处:当线程很多时,每个线程都会区判断同步上的锁,这是很耗资源的,无形中会降低程序的运行效率
3. 同步方法
- 就是把synchronized关键字加到方法上
- 格式:
- 修饰符 synchronized 返回值类型 方法名(方法参数) { }
- 同步方法的锁对象:this
- 同步静态方法的锁对象:类名.class
- 格式:
- 修饰符 static synchronized 返回值类型 方法名(方法参数) { }
4. 线程安全的类
1. StringBuilder:
- 线程安全,可变的字符序列
2. Vector:
- 该类实现了List接口,使其成为Java Collections Framework的成员
- 与新的集合实现不同,Vector被同步。如果不需要线程安全,建议使用ArrayList代替Vector
3. Hashtable:
- 该类实现了哈希表。任何非null对象都可以用作键或者值
- 该表实现了Map接口,使其成为Java Collections Framework的成员
- 与新的集合实现不同,Vector被同步。如果不需要线程安全,建议使用HashMap代替Hashtable
4.
Collections.synchronizedList //返回由指定列表变成的线程安全列表
例如:List<String> list = Collections.synchronizedList(new ArrayList<String>());
5. Lock锁
Lock提供比 synchronized() 更广泛的锁定操作
- void lock() //上锁
- void unlock() //释放锁
Lock锁是接口 不能直接实例化,采用实现类ReentrantLock来实例化 (多态)
- 构造方法 ReentrantLock()
- 例子:
private Lock lock = new ReentrantLock(); lock.lock(); lock.unlock();
有异常可以用 try () { } finally () { } ,来保证unlock( ) 开锁一定执行
3. 生产者与消费者
- 十分经典的多线程写作模式
- 一类是消费者用于消费数据
- 一类是生产者用于生产数据
- 生产者 —> 共享数据区域 <— 消费者
void wait() //导致当前线程等待,直到另一个线程调用该对象的notify()方法或者notifyall()方法
void notify() //唤醒正在等待对象监视器的单个进程
void notifyall() //唤醒正在等待对象监视器的所有进程