java技术学习技术文程序员

线程

2016-06-29  本文已影响445人  jacky123

线程的状态


线程方法

1. notify/notifyAll

Wakes up all threads that are waiting on this object's monitor. A thread waits on an object's monitor by calling one of the {@code wait} methods.
This method should only be called by a thread that is the owner
of this object's monitor.

一旦一个对象调用了wait方法,必须要采用notify()和notifyAll()方法唤醒该进程;


关于线程的常见问题

1. Object的wait和notify/notifyAll如何实现线程同步?

在Object.java中,定义了wait(), notify()和notifyAll()等接口。
wait()的作用是让当前线程进入等待状态,同时,当object调用wait()方法会让当前线程释放它所持有object对象锁。
而notify()和notifyAll()的作用,则是唤醒在此对象监视器上等待的单个/全部线程。

a.关于wait的一个错误案例:

final Object object = 1;

new Thread(){
    @Override
    public void run() {
        synchronized (object){
            Log.e("jack",Thread.currentThread().getName()+"->"+1);
            try {
                /**
                 * object not locked by thread before wait(),
                 * 这是因为我们锁住的是object对象,但是wait,相当于this.wait,解锁的是当前对象。
                 * 当前对象并没有locked,所以会有这个错误。
                 */
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Log.e("jack",Thread.currentThread().getName()+"->"+2);
        }
    }
}.start();

b.关于notify的一个案例,注意同步对象:

//是否满足某种条件的标识
boolean flag = false;

public void onWait(View view) {
    //每次点击初始化 falg 的值
    flag = false;
    final Thread t1 = new Thread("Thread 1") {
        @Override
        public void run() {
            /**
             * 这边锁住的是 MainActivity 的对象。
             * 在run方法里通过 wait 释放 MainActivity对象锁,如果想要再次唤起这个线程,肯定还是
             * MainActivity.this.notify();
             *
             * 如果这边同步this,则代表当前线程对象。
             */
            synchronized (MainActivity.this) {
                //不满足条件就在这里等待
                while (!flag) {
                    Log.e("jack", Thread.currentThread().getName() + "->" + 1);
                    try {
                        MainActivity.this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Log.e("jack", Thread.currentThread().getName() + "->" + 2);
                }
            }
        }
    };
    t1.start();

    Thread t2 = new Thread("Thread 2") {
        @Override
        public void run() {
            try {
                //保证"Thread 1"先执行
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (MainActivity.this) {
                try {
                    Log.d("jack", Thread.currentThread().getName() + "->" + 3);
                    Thread.sleep(1000);
                    flag = true;   //满足了某种条件
                    /**
                     * 唤醒在 MainActivity.this 对象监视器上等待的单个/全部线程。
                     */
                    MainActivity.this.notify();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Log.d("jack", Thread.currentThread().getName() + "->" + 4);
            }
        }
    };
    t2.start();
}
Paste_Image.png

线程1执行打印了 "Thread 1->1",然后通过 MainActivity.this.wait();释放了当前线程所持对象的锁...

2. wait和yield(或sleep)的区别?

wait()是让线程由“运行状态”进入到“等待(阻塞)状态”
yield()是让线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程有机会获取执行权;但是,并不能保证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权。
wait()是会在线程释放它所持有对象的同步锁,而yield()方法不会释放锁。
Thread.sleep(long millis)和Thread.sleep(long millis, int nanos)静态方法强制当前正在执行的线程休眠.当线程睡眠时,它入睡在某个地方,在苏醒之前不会返回到可运行状态。当睡眠时间到期,则返回到可运行状态。


线程同步

1. wait notify 来实现

以android中的HandlerThread的源码为例说明

@Override
public void run() {
    mTid = Process.myTid();
    Looper.prepare();
    synchronized (this) {
        /**
         * 获取到当前Thread的Looper对象
         * 然后通知 getLooper 方法,这个时候可以返回(同步)
         */
        mLooper = Looper.myLooper();
        notifyAll();
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    Looper.loop();
    mTid = -1;
}

public Looper getLooper() {
    if (!isAlive()) {
        return null;
    }
    
    // If the thread has been started, wait until the looper has been created.
    synchronized (this) {
        while (isAlive() && mLooper == null) {
            try {
                /**
                 * 等待run方法的Looper对象初始化完成
                 */
                wait();
            } catch (InterruptedException e) {
            }
        }
    }
    return mLooper;
}
2. synchronized

a. 说一下 synchronized与static synchronized 的区别

synchronized是对类的当前对象进行加锁,防止其他线程同时访问该对象的所有synchronized块,其实synchronized就相当于this.synchronized
static synchronized恰好就是要控制类的所有对象的访问了,static synchronized的作用是同步线程访问该类的所有对象代码块。

3. CountDownLatch

一个同步辅助类(大名鼎鼎的java.util.concurrent包),在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。

4. 重入锁ReentrantLock

lock
unlock
isHeldByCurrentThread
getHoldCount

上一篇下一篇

猜你喜欢

热点阅读