Android多线程研究(4)——从一道面试题说起

Android多线程研究(4)——从一道面试题说起

大家好,又见面了,我是全栈君,祝每个程序员都可以多学几门语言。

有一道这种面试题:开启一个子线程和主线程同一时候运行,子线程输出10次后接着主线程输出100次,如此重复50次。先看以下代码:

package com.maso.test;

/**
 * 
 * @author Administrator
 * 两个线程,当中是一个主线程,第一个线程先运行输出10次,主线程接着运行输出100次,如此重复50次
 */
public class ThreadTest3 implements Runnable{
	private static Test test;
	@Override
	public 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。

以下我们来看看线程的生命周期:

<span>Android多线程研究(4)——从一道面试题说起</span>

实现线程调度的方法例如以下:

1、sleep():该线程是让线程休眠一定的时间,须要捕获InterruptedException

2、yield():暂停当前线程,让同等级优先权的线程运行,假设没有同等级优先权线程则不会起作用。起作用后会让出CPU运行时间,进入就绪状态。

3、join():让一个线程等待调用join方法的线程运行完成后再继续运行。

<span>Android多线程研究(4)——从一道面试题说起</span>

看一段代码:

public class ThreadTest4 implements Runnable{
	private static int a = 0;
	@Override
	public 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;
	@Override
	public 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()方法的作用由此可见,它会让其它线程等待该线程运行完成后再运行。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/118988.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • Java Web 网络商城案例演示十五 订单详情功能(提交订单支付界面)

    Java Web 网络商城案例演示十五 订单详情功能(提交订单支付界面)订单详情功能(提交订单支付界面)原理分析步骤实现:1、准备工作:order_list.jsp当中修改链接提交当前订单编号<ahref=”${pageContext.request.contextPath}/OrderServlet?method=findOrderByOid&oid=${o.oid}”>付款</a>2、OrderServlet…

  • 对日外包十日谈 之 我所了解的对日外包企业

    对日外包十日谈 之 我所了解的对日外包企业对日外包十日谈之我所了解的对日外包企业蒋彪2010-5-23于上海浦东1.  前言关于对日外包,我其实本来已经不想说些什么了。因为,我已经离开了对日外包行业。这个行业的是与非,正确与错误,我都不想评论什么了。但是唯一的,我觉得我还是应该把承诺的文章写完。有很多人问我,对日外包这个行业怎么样,我不知道该说些什么。如果你只是把这个职业看作是生存的手段,那么无可厚非。如果你

  • vim编辑器重要快捷键及vim设置「建议收藏」

    vim编辑器重要快捷键及vim设置「建议收藏」1.全选:ggVG2.跳转到文本最后一行:shift+g3.跳转到文本第一行:gg4.跳转到光标所选行的行首位置:05.跳转到光标所选行的行尾位置:shift+46.全部替换(替换无需确认)::%s/src/dst/g7.全部替换(每次替换需要确认)::%s/src/dst/gc8.查找:/string9.高亮显示查找到的内容::sethlsearch10.显示vim行号::setnu!11.到注释的开始:[/12.到注释的结束:]/13.撤销上一次操作:

  • Jlink或者stlink用于SWD接口下载程序

    Jlink或者stlink用于SWD接口下载程序最近要使用stm32f103c8t6最小系统板,直接ISP串口下载程序太麻烦,就想着使用swd接口来调试。结果:通过SWD接口下载程序成功,但调试失败,还不知原因,会的的人麻烦交流一下。SWD接口:3.3VDIO(数据)CLK(时钟)GND1.首先声明jlink和stlink都有jtag和swd调试功能。jlink接口如下:如图,我使用的就是VCC…

  • hdu4288 Coder(段树+分离)

    hdu4288 Coder(段树+分离)

  • 12.Java- Maven 教程

    12.Java- Maven 教程一、安装引用菜鸟教程:Maven菜鸟教程地址1.下载1.Maven链接Maven下载地址:,点击跳转2.选择版本3.解压到指定地址4.并配置环境变量,引用的菜鸟教程引用菜鸟教程,菜鸟教程路径地址,点击跳转右键“计算机”,选择“属性”,之后点击“高级系统设置”,点击”环境变量”,来设置环境变量,有以下系统变量需要配置:新建系统变量MAVEN_HOME,变量值:E:\Maven\apache-maven-3.3.9编辑系统变量Path,添加变量值:;%M

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号