Java线程

资料整理:

多线程(一)、基础概念及notify()和wait()的使用

多线程(二)、内置锁 synchronized

多线程(三)、线程池 ThreadPoolExecutor 知识点总结

多线程(四)、Android多线程使用及AsyncTask源码分析

使用整理:

线程是什么:

  1. Thread是线程,而且有自己的生命周期
  2. 线程常用的操作有:wait(等待)、notify(唤醒)、notifyAll、sleep(睡眠)、join(阻塞)、yield(礼让)
  3. wait、notify、notifyAll都必须在synchronized中执行,否则会抛出异常
  4. synchronized和ReentrantLock锁都是辅助线程使用的

创建线程:

  1. 新建一个类继承Thread,并重写run方法,调用方实例化该类,并调用.start()方法。
  2. 新建一个类实现Runnable接口,并重写run方法,调用方在声明Thread的同时,构造参数里传入该实例化对象,然后用Thread的.start()即可。
  3. 直接在需要实现子线程的类里面New一个Thread类,并实现run方法.最后记得.start()才会开始执行。

线程的常用方法:

这三个是Thread类里的方法

  • sleep()

sleep()作用是让线程休息指定的时间,时间一到就继续运行,该方法为静态方法。

  • join()

join()作用是让指定的线程先执行完毕后再执行其他代码,在等待期间会阻塞主线程,该方法为成员方法。

  • yield()

作用是指定线程礼让一下让别的线程先执行,yield()执行开始后,后面的代码会进入等待状态,除非其它线程执行完毕,才会接着从yield()后面的代码开始执行,如果别的线程在执行期间也进行了礼让,那么再没有礼让的线程执行完毕后,礼让过后的线程如果没开启同步锁,则会进入抢占资源同时执行。该方法是一个静态方法。

打印当前线程:

  Log.i("wagesPay", "当前线程是" + Thread.currentThread().getName());

线程同步:

线程默认情况下是不安全的,也就是多个线程都调用同一个方法,它们会在同一时刻执行(执行顺序跟抢占资源有关),而这个时候因为某一些属性值的同时更改,可能会发生一些不必要的错误,所以要想多个线程都有序的执行,需要用到线程同步。

synchronized:

对象锁和类锁的区别:

对象锁:
锁住的是对象区域,如果两个方法同时加上了对象锁,两个线程用一个对象实例同时调用这两个方法,那么线程一里面的方法执行完毕后,才会继续执行线程2的方法,如果线程2里的方法把对象锁去掉,只加锁方法1,那么则会两个线程里的方法同步执行(抢占资源),如果两个线程用的是不同的对象实例去执行方法1和方法2,虽然两个方法都加上了对象锁,但还是会同步执行(抢占资源),所以对象锁只局限于某一个对象,同一个类不同的对象,会有不同的判断区域。

类锁:
锁住的是类区域,不同的对象,但是同一个类,多个线程同时访问类锁里的代码块,则会依次执行(不进行抢占资源)如果两个方法分别加上了对象锁,和类锁,两个线程用同一个对象实例调用这两个方法,那么则会两个线程里的方法同步执行(抢占资源),因为一个方法是类锁,一个方法是对象锁,它们的作用域不同,判断方法也不同,对象锁的方法里判断该实例对象是第一次进来,所以会执行,而在类锁的方法里判断该实例也是第一次进到类锁的代码块里,所以也会执行,如果再来一个线程3,继续同时执行类锁里的代码块,则会进入等待状态。

1.方法声明上添加synchronized,如果是静态方法,则代表为类锁,否则为对象锁

示例:

public synchronized void sellTicket(){
    //代码块
}

2.方法内添加synchronized

public void sellTicket(){
//参数传入某一个对象实例,或者某一个类,分别代表为该锁为对象锁,还是类锁
        synchronized(参数){
            //代码块
        }
}

线程的等待与唤醒:

分别为wait()、notify()、notifyAll(),这三个方法在Object类里,而Object类是所有类的基类,也就是任意对象都持有这三个方法。但是这三个方法都必须在synchronized中执行,否则会抛出异常。

  • wait()

开始等待后,后面的代码不再执行,除非调用了唤醒。

  • notify()

对指定区域调用唤醒,等待的代码才可继续执行。

  • notifyAll()

唤醒某个区域里面的所有等待。

ReentrantLock:

ReenTrantLock有两个构造方法,一个空参,另一个ReenTrantLock(boolean fair)当参数fair=true时,表示构造一个公平锁。synchronized是非公平锁,公平锁会按时间顺序,先唤醒等待队列中等待的线程。公平锁的一大特点就是不会产生饥饿现象。但是,由于实现公平锁要求系统维护一个有序队列,因此实现公平锁的成本很高,性能也相对低下。因此,默认情况锁是非公平的。需要注意的是,千万不要忘记调用unlock来释放锁,否则可能会引发死锁等问题。

示例:

Lock lock=new ReentrantLock();
   public void doSth() {
        lock.lock();
        try {
            //代码块

        } finally {
            lock.unlock();
        }
    }

如果ReentrantLock是一个局部变量,两个线程用同一个对象实例去调用这个方法,那么两个线程里的方法会同步执行(抢占资源),原因是局部变量的作用域范围不同,因为局部变量每次进来都是一个新对象,而新对象获取锁时锁的状态因为是空闲状态,所以可以获取到,改为成员变量才会保存锁的状态。

ReenTrantLock的一些常用方法(必要时可参考官方文档)

  • lock()

获得锁,如果锁已经被占用,则等待

  • lockInterruptibly()

获得锁,但优先响应中断。如果当前线程未被中断,则获取锁

  • tryLock()

尝试获得锁,如果成功放回true,失败返回false,该方法不等待,立即返回

  • unlock()

释放锁

  • newCondition()

返回与lock实例中的Condition对象

Condition的使用
* 使用ReentrantLock类的newCondition()方法可以获取Condition对象

* 需要等待的时候使用Condition的await()方法, 唤醒的时候用signal()方法

* 不同的线程有不同的Condition, 这样就能区分唤醒的时候找哪个线程了

Condition接口:此接口中封装了awiat(),signal(),signalAll(),方法。代替了原来锁中的wait(),notify(),notifyAll()监视器方法

ReenTranLock解决死锁的方式:

  • 响应中断

通过lock.lockInterruptibly()方法来实现。对于synchronized来说,对于一个线程在等待锁。那么只有两种情况,要么获得锁,要么保持等待。重入锁提供另一种可能中断,如果一个线程在等待锁,如果它收到一个通知,被告知无需再等待,可以停止工作了。这种情况对于处理死锁是有帮助的

  • 锁申请等待限时

通过lock.tryLock()方法来实现。如果其他线程占有锁,则当前线程不会等待,立即返回false。tryLock(long ,TimeUnit),tryLock方法既可以接受无参调用,还可以接受参数,第一个参数等待时长,第二个表示计时单位。如果超过等待时长还没有获取到锁,会停止等待并返回false。

tryLock和lock和lockInterruptibly三个方法的区别:
(1)tryLock仅在其他线程未保持锁时,才获取锁,并立即返回true。如果锁已经被其他线程保持,就立即返回false。tryLock(long timeout,TimeUnit unit),可以增加时间限制,如果超过该时间段还没获得锁,返回false。

(2)lock能获得锁就返回true,不能的话一直等待获得锁

(3)lock和lockInterruptibly,如果两个线程分别执行这两个方法,但此时中断这两个线程,前者不会抛出异常,而后者会抛出异常InterruptedException。lockInterruptibly方法在其他线程在中断当前线程时,在抛出异常的同时,会停止等待获取锁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值