多线程创建的四种方式
- 继承Thread
- 实现Runnable接口
守护线程和主线程
java线程分为两类
第一类是守护线程,第二类是主线程
守护线程依赖于主线程,当主线程结束后,守护线程也会消失。比如Java垃圾回收机线程依赖于主线程,垃圾回收机线程就是main函数的守护线程。
线程的几种状态:
- 新建:当一个Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建的状态。
- 就绪:处于新建状态的线程被start()后,将进入线程队列并等待CPU时间片,此时他已经具备了运行条件,只是没分配到CPU资源。
- 运行:当就绪的线程被调度并获得CPU资源时,便进入运行状态,run()方法定义了线程的操作和功能
- 阻塞:在某种特殊情况下,被人为挂起或执行输入输出操作时,让出CPU并临中止自己的执行,进入阻塞状态。
- 死亡:线程完成了他的全部工作或线程被提前强制性的中止或出现异常导致结束
java线程安全的解决
java通过同步机制来解决线程安全问题
- 同步代码块
synchronized (同步监视器){ //同步监视器,俗称锁,这里是一个一个对象
//需要同步的代码
}
- 同步方法
如果操作共享数据的代码正好在一个方法中,那么我们可以声明这个方法为gongxiangfangfa
public synchronized void show(){//默认的同步监视器为this
}
注意
- 同步方法仍然要涉及到同步监视器,只是不需要我们显示的声明
- 非静态d的同步方法,同步监视器:this
- 静态的同步方法,同步监视器是:当前类本身
- lock锁(jdk5.0新特性)
private ReentrantLock lock = new ReentrantLock();
lock.lock()l
lock.unlock();
线程安全模式在单例模式中的引用
没有线程安全的单例模式
public class demo {
private static demo instance;
public static demo getInstance(){
if(instance == null){
instance = new demo();
}
return instance;
}
}
线程安全单例模式
public class demo {
private static demo instance;
public static demo getInstance(){
if(instance == null){
synchronized (demo.class){
if(instance == null){
instance = new demo();
}
}
}
return instance;
}
}
线程通信
- wait():一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器
- notify():一旦执行此方法,就会唤醒被wait的一个线程,如果有多个线程被wait,就唤醒优先级高的进程
- notifyAll():一旦执行此方法发,就会唤醒所有被wait的进程
注意
- wait(),notify(),notifyAll()三个方法必须使用在同步代码块或同步方法中。
- wait(),notify(),notifyAll()三个方法的调用者必须是同步代码块或同步方法中的同步监视器
- wait(),notify(),notifyAll()三个方法是定义在Object类中的
新增线程实现方法
实现Callbale接口
与Runnable相比,Callable功能更加强大。与run()相比
- 有返回值
- 可以抛出异常
- 支持泛型返回值
- 需要借助Future类,比如获取返回结果
线程连接池
背景:
经常创建和销毁,使用量特别大的资源,比如并发情况下的线程,对性能影响很大。
思路:
提前创建好多个线程,放入线程池中,使用时直接获取,使用完返回线程池,可以避免频繁创建销毁,实现重复利用。类似生活中的公交车例子。
好处
- 提高响应速度(减少创建线程池的时间)
- 降低资源消耗(重复利用线程池中线程,不需要每次都创建)
- 便于管理线程