Android多线程研究(4)——从一道面试题说起
来源:互联网 发布:软妹小九九淘宝店 编辑:程序博客网 时间:2024/04/29 11:59
有一道这样的面试题:开启一个子线程和主线程同时运行,子线程输出10次后接着主线程输出100次,如此反复50次。先看下面代码:
package com.maso.test;/** * * @author Administrator * 两个线程,其中是一个主线程,第一个线程先运行输出10次,主线程接着运行输出100次,如此反复50次 */public class ThreadTest3 implements Runnable{private static Test test;@Overridepublic void run() {for(int i=0; i<50; i++){test.f1(i);}}public static void main(String[] args) {test = new Test();new Thread(new ThreadTest3()).start();for(int i=0; i<50; i++){test.f2(i);}}/** * 将控制和逻辑及数据分类(该类就是数据) * @author Administrator * */static class Test{private boolean isf1 = true;/** * 输出10次 */public synchronized void f1(int j){if(!isf1){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}for(int i=1; i<=10; i++){System.out.println(Thread.currentThread().getName() + "第" + j + "次轮巡,输出" + i);}isf1 = false;notify();}/** * 输出100次 */public synchronized void f2(int j){if(isf1){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}for(int i=1; i<=100; i++){System.out.println(Thread.currentThread().getName() + "第" + j + "次轮巡,输出" + i);}isf1 = true;notify();}}}上面判断用的是if语句,这样做看似没有什么问题,实际上这样做是不安全的,因为线程在等待的过程中有可能被假唤醒,所以我们需要使用while语句。另外在使用wait和notify的时候需要注意一下几点:
1、调用object的wait方法和notity方法时,必须先获得object的对象锁(必须写在synchronized中)。
2、如果调用了object的wait方法,则该线程就放掉了对象锁。
3、如果A1、A2、A3都在object.wait(),则B调用object.notify()只能唤醒A1、A2、A3中的一个(具体哪一个由JVM决定)
4、object.notifyAll()能够唤醒全部。
5、B在唤醒A的时候,B如果还持有对象锁,则要等到B释放锁后,A才有机会执行。
Sleep和Wait有什么区别?
sleep()并不释放对象锁,wait()释放对象锁。但是wait()和sleep()都可以通过interrupt()方法打断线程的暂停状态,从而使线程立刻抛出InterruptedException。如果线程A希望立即结束线程B,则可以对线程B对应的Thread实例调用interrupt方法。如果此刻线程B正在wait/sleep/join,则线程B会立刻抛出InterruptedException,在catch() {} 中直接return即可安全地结束线程。需要注意的是,InterruptedException是线程自己从内部抛出的,并不是interrupt()方法抛出的。对某一线程调用interrupt()时,如果该线程正在执行普通的代码,那么该线程根本就不会抛出InterruptedException。但是,一旦该线程进入到wait()/sleep()/join()后,就会立刻抛出InterruptedException。
下面我们来看看线程的生命周期:
实现线程调度的方法如下:
1、sleep():该线程是让线程休眠一定的时间,需要捕获InterruptedException
2、yield():暂停当前线程,让同等级优先权的线程运行,如果没有同等级优先权线程则不会起作用。起作用后会让出CPU运行时间,进入就绪状态。
3、join():让一个线程等待调用join方法的线程执行完毕后再继续执行。
看一段代码:
public class ThreadTest4 implements Runnable{private static int a = 0;@Overridepublic void run() {for(int i=0; i<10; i++){a++;}}public static void main(String[] args) {new Thread(new ThreadTest4()).start();System.out.println(a);}}这段代码会输出10吗?答案是不会的,因为在启动子线程后,就立马输出了a的值,此时子线程对a还没有操作。修改如下:
public class ThreadTest4 implements Runnable{private static int a = 0;@Overridepublic void run() {for(int i=0; i<10; i++){a++;}}public static void main(String[] args) throws InterruptedException {Thread t = new Thread(new ThreadTest4());t.start();t.join();System.out.println(a);}}这回输出了10,join()方法的作用由此可见,它会让其他线程等待该线程执行完毕后再执行。
- Android多线程研究(4)——从一道面试题说起
- 从一道++操作面试题说起(Javap)
- Coder的困惑,从一道面试题说起(downmoon)
- 一道多线程面试题
- 【原创】由一道面试题说起
- 由一道python的面试题说起
- 从一道面试题说去4
- 一道多线程的面试题
- 一道面试题引发的对android中context的研究(二)
- 一道多线程面试题分析(控制输出顺序)
- android的一道面试题
- 一道数据库面试题—更新
- 一道多线程面试题-C语言实现
- java-多线程-一道阿里面试题分析
- 一道多线程面试题解法总结
- 一道阿里多线程面试题分析
- 一道很经典的多线程面试题
- 三年高考五年模拟——从一道面试题探寻JavaScript的套路
- 通过注册表获取某款软件的信息
- 出错hh未定义标示符,是怎么回事?
- 2014年百度之星程序设计大赛 - 资格赛题解
- MySQL 5.1 免安装版的配置(图文教程)
- oracle教程
- Android多线程研究(4)——从一道面试题说起
- 离散信号MATLAB频谱分析程序
- QOS技术及配置实例
- 用户在文本框中输入需要转换的十进制数,通过点击3个按钮在标签中显示结果。(点击一个实现一个)
- 怎样成为一名Android开发者
- C++之const
- 目标检测的图像特征提取之LBP特征
- java文件读写操作大全
- 任务调度的使用crontab