Java多线程
- 线程就是独立的执行路径
- 程序在运行的时候,即使没有自己创建线程,后台也有多个线程
- main是主线程,是系统的入口,用以执行整个程序
- 进程中如果开辟了新的线程,线程运行由调度器安排,调度器是与操作系统紧密相连的先后不能干预
- 同一个资源存在的资源争夺的情况,需要考虑到并发控制
- 线程会带来额外的开销、如CPU调度时间,并发控制
- 线程在自己的工作内存交互,内存控制不当会造成数据的不一致
线程的创建方式
继承Thread类
- 子类对象具有多线程能力
- 启动线程:子类对象.start()
- 不建议使用 避免OOP单继承的局限性
实现Runnable接口
- 实现runnable接口具备多线程能力
- 启动线程:传入目标对象+thread对象.start()
- 推荐使用:避免单继承的局限性,方便灵活,方便对象被多个线程使用
实现callable接口:
-
实现callable接口,需要返回值类型
-
重写call方法,需要跑出异常
-
创建的目标对象
-
具体的实现步骤
//创建执行服务 ExecutorService ser = Executors.newFixedThreadPll(1); //提交执行 Future<Boolean> result1 = ser.submit(t1); //获取结果 boolean r1 -result1.get(); //关闭服务 ser.shutdownNow();
线程的五大状态:参考操作系统
new、就绪、阻塞、运行、dead
守护线程
锁
锁的对象应该是共享的量 JDK5以后可以通过显式定义同步锁实现对象同步。java.until.concurrent.locks.Lock接口实现。每次只能由一个线程对Lock对象加锁,线程开始访问共享资源之前需先获得Lock对象
ReentranLock类实现了Lock,与Synchronize的拥有相同并发性与内存语义。
class TestLock implements Runnable{
private final ReentrantLock lock = new ReentrantLock();
@Override
public void run(){
try{
lock.lock();
}finally{
lock.unlock
}
}
}
synchronized是隐式锁,不建议相应的代码块的里面有大量的代码,出了代码块以后自动释放;其拥有方法锁与代码块锁
因此使用的优先级 Lock>同步代码块>同步方法
生产者消费者
线程池
经常u使用或者销毁,使用的特别大的资源,并发情况下对于性能的影响是十分大的。提前创建好多个线程,放入线程池中,使用时获取、使用完成以后放回到池中,避免重复创建销毁,实现重复利用。