Java中的线程
线程的定义
线程 - 进程中的进程,就是线程,使用java实现的并发,线程也是java程序执行的最小单位,我们通常使用的main方法就是一个线程;
线程的创建
1.继承Thread父类,重写run方法。启动线程使用start方法;
2.实现Runnable接口,实现run方法,创建Thread对象,使用对象调用start方法;
线程一旦启动,和启动它的线程就是两个完全独立的运行单元,谁先执行谁后执行取决于谁能抢到CPU资源;
线程的同步问题 - 当多个线程并发访问一个共享资源(对象)的时候,有可能引发同步问题;
例如:火车代售票点
线程同步问题
解决多线程同步问题 - 锁机制 - 就是给共享资源加锁;(排他锁)
第一种方法 - 互斥
synchronized关键字 - 给对象加锁;
1、放在方法定义前面 - public synchronized void f(){ // - 加锁
//需要同步的代码
} // - 解锁
优点:简单易懂;
缺点:无论是否需要同步的代码都串行,效率低;
2、synchronized 块 - synchronized (需要被加锁对象){ // - 加锁
//需要同步执行的代码
} // - 解锁
优点:需要同步的代码块同步执行,不需要同步的代码可以并发执行,这样提高运行效率;
缺点:不好理解;
第二种方法 - 协作
生产者 - 消费者模型 - 产品(共享资源) :
生产者在生产产品之前,消费者不能消费,消费者在消费完产品之前,生产者不能生产;
wait(); - 等待
notify();notifyAll();- 通知(所有)
例如 :麦当劳免费续杯;
它是实现线程池、数据库连接池、高速缓存等的主要思想;
线程的状态
线程五个状态 - 1.新建状态 - 线程对象已经建立,但是没有调用start方法之前;
2.就绪状态 - 调用start方法后,会进入就绪队列中;等待cpu;(线程调度程序)
3.执行状态 - 线程调度程序分配cpu资源后,线程执行;
4.阻塞状态 - 当调用wait、sleep方法,或进行IO操作,等待网络连接请求等;
5.死亡状态 - a)自然死亡 - run方法执行完毕,程序正常结束;
b)突然死亡 - 在线程执行过程中,调用stop、interrupt方法时,强制线程终止;
总结
思考:wait和sleep方法的区别?
1.sleep方法设定了一个时间,当时间到的时候,线程会自动被唤醒进入就绪状态;wait只有被notify才能被唤醒;
2.sleep方法是Thread类的静态方法,而wait是Object提供的,所有的java类都能调用它;
3.sleep方法的调用是不需要锁的,而wait方法的调用是需要锁的,并且在调用完以后还会解锁;