多线程
多线程创建的两种方式:
①继承Thread类创建多线程
②实习Runnable接口创建多线程
第二种相对于第一种的好处:
①适合多个相同程序代码的线程去处理同一个资源的情况,把线程同程序代码、数据有效的分离,很好地体现了面向对象的设计思想。
②避免java单继承带来的局限性。Eg:使用一个已经继承了某一个类的子类创建线程,由于一个类不能同时有两个父类,所以不能用继承Thread类的方式。
后台线程:在java中,只要还有一个前台线程在运行,进程就不会结束,一个进程中只有后台线程,进程会结束,新创建的线程默认为前台线程。把线程变为后台线程需要对象启动前调用setDaemon(true)方法。
线程的生命周期
当Thread对象创建完成时,线程的生命周期便开始了。当run()方法中的代码正常执行完毕或者线程抛出异常或错误时,线程生命周期结束。
线程生命周期的五种状态:新建状态、运行状态、阻塞状态、死亡状态。
线程调度
Jvm默认采用抢占式调度。
处于就绪状态(调用start()方法)的线程都有自己的优先级,可以通过setPriority(int new Priority)方法进行设置。
线程休眠,sleep()静态方法可以控制正在运行的线程休眠让别的线程执行,休眠结束,线程会返回到就绪状态。
线程让步,yield()方法可以让正在运行的线程暂停,yield()方法不会阻塞该线程,只是将线程转换为就绪状态,让系统的调度器重新再调度溢出。
线程插队,当在某个线程中调用其他线程的join()方法时,调用的线程将会被阻塞,直到被join()方法加入的线程执行后它才会继续运行。
线程安全
线程安全问题:多个线程同时处理共享资源造成数据不一致。
解决方案:同步机制
①同步代码块
Synchronized(lock){
操作共享资源代码块
}
Lock是锁对象,默认情况是1,线程执行同步代码块并将锁的标志位为0.当新的线程执行时新发生阻塞,当前线程同步代码块执行完毕锁标志位变为1,新线程才能执行。类似于公用电话。
②同步方法
语法格式: 权限修饰符 Synchronized 返回值类型 方法名([参数1,...]){}
被synchronized修饰的方法在某一个时刻只允许一个线程访问,访问该方法的其他线程都会发生阻塞,当前线程访问完毕,其他线程才有机会执行方法。