少年游

欲买桂花同载酒,终不似,少年游。

0%

Thread的方法介绍和使用场景

1
2
3
4
5
6
7
8
9
Thread implements Runnable
run();
start();
join();
sleep();
yield();
wait();
notify();
interrupted();

run()

  • run()方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到写线程的目的。
  • 调用start方法方可启动线程,把需要并行处理的代码放在run()方法中,start()方法启动线程将自动调用 run()方法,这是由jvm的内存机制规定的。
  • run()方法必须是public访问权限,返回值类型为void.。

start()

  • 用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。
  • 通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行run()方法。
  • 方法 run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止。

join()

  • Java Thread中, join() 方法主要是让调用改方法的thread完成run方法里面的东西后, 在执行join()方法后面的代码。
  • 使用场景: 主线程开启子线程,子线程进行网络访问,然后获得结果,填充数据至UI。
  • 线程同步,除了join()方法外,目前安卓中还有另外一个Handler,Message
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    Handler mHandler = new Handler() {  

    @Override
    public void handleMessage(Message msg) {
    super.handleMessage(msg);
    switch (msg.what) {
    case 0:
    //完成主界面更新,拿到数据
    String data = (String)msg.obj;

    updateWeather();
    textView.setText(data);
    break;
    default:
    break;
    }
    }

    };

在子线程中,通过传递Message对象给handler处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private void updateWeather() {  

new Thread(new Runnable(){

@Override
public void run() {
//耗时操作,完成之后发送消息给Handler,完成UI更新;
mHandler.sendEmptyMessage(0);
//需要数据传递,用下面方法;
Message msg =new Message();
msg.obj = "数据";//可以是基本类型,可以是对象,可以是List、map等;
mHandler.sendMessage(msg);
}

}).start();

}

sleep()

sleep是让线程指定休眠时间,然后继续工作

yield()

yiedld这个方法是让当前线程回到可执行状态,以便让具有相同优先级的线程进入执行状态,但不是绝对的。因为虚拟机可能会让该线程重新进入执行状态。

wait()

wait是等待,直到有线程通知notify()唤醒他才会重新工作。

sleep与wait的区别:

  • sleep是你困了,要睡觉,等你睡醒了再干活。
  • wait是你现在没事做,先眯会儿吧,什么时候领导提醒你该干活了再干。

简单点说wait和sleep的区别:

  1. wait只能在有线程锁的部分调用,而sleep不需要。
  2. wait是睡眠时放开线程锁,此时线程不占用任何资源,不增加时间限制。而sleep睡眠时占着线程锁占着CPU不工作,形象地说明为“占着CPU睡觉”,此时,系统的CPU部分资源(同步资源)被占用,其他线程无法进入,会增加时间限制。
  3. wait需要notify方法来唤醒,而sleep是定时醒。

notify()

Wait()和notify():如果条件不满足,则等待。当条件满足时,等待该条件的线程将被唤醒。
一般用在synchronized机制中

1
2
3
4
5
6
7
8
例如:
线程A
synchronized(obj) {
while(!condition) {
obj.wait();
}
obj.doSomething();
}

当线程A获得了obj锁后,发现条件condition不满足,无法继续下一处理,于是线程A就wait()。
在另一线程B中,如果B更改了某些条件,使得线程A的condition条件满足了,就可以唤醒线程A:

1
2
3
4
5
线程B
synchronized(obj) {
condition = true;
obj.notify();
}

需要注意的概念是:

  • 调用obj的wait(), notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj) {……} 代码段内。
  • 调用obj.wait()后,线程A就释放了obj的锁,否则线程B无法获得obj锁,也就无法在synchronized(obj) {……} 代码段内唤醒A.
  • 当obj.wait()方法返回后,线程A需要再次获得obj锁,才能继续执行。
  • 如果A1,A2,A3都在obj.wait(),则B调用obj.notify()只能唤醒A1,A2,A3中的一个(具体哪一个由JVM决定)。
  • obj.notifyAll()则能全部唤醒A1,A2,A3,但是要继续执行obj.wait()的下一条语句,必须获得obj锁,因此,A1,A2,A3只有一个有机会获得锁继续执行,例如A1,其余的需要等待A1释放obj锁之后才能继续执行。
  • 当B调用obj.notify/notifyAll的时候,B正持有obj锁,因此,A1,A2,A3虽被唤醒,但是仍无法获得obj锁。直到B退出synchronized块,释放obj锁后,A1,A2,A3中的一个才有机会获得锁继续执行。

interrupted()

  1. interrupt:置线程的中断状态
  2. isInterrupt:线程是否中断
  3. interrupted:返回线程的上次的中断状态,并清除中断状态