Java多线程与并发应用-(4)-传统线程通信技术试题

package com.lipeng;

public class LoopDemo {

	/**
	 * 线程A循环10次,然后线程B循环100次,然后A再循环10次,然后B再循环100次。如此循环50次。
	 * lipeng
	 * 2015-4-10
	 * @param args
	 */
	public static void main(String[] args) {
		MyTask task=new MyTask();
		RunA runA=new RunA(task);
		RunB runB=new RunB(task);
		new Thread(runA,"A").start();  //每个线程的start方法只能运行一次,但Run方法在不同的线程中可以运行多次。
		new Thread(runB,"B").start();
	}
}

class RunA implements Runnable
{
	private MyTask task;
	public RunA(MyTask task)
	{
		this.task=task;
	}
	@Override
	public void run() {
		try {
			for(int i=0;i<50;i++)
			{
				task.A();
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
class RunB implements Runnable
{
	private MyTask task;
	public  RunB(MyTask task)
	{
		this.task=task;
	}
	@Override
	public void run() {
		try {
			for(int i=0;i<50;i++)
			{
				task.B();
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
class MyTask
{
	private boolean aGo=true;//切换开关,当true时A执行,false时B执行,执行完后切换条件
	public synchronized void A()throws Exception{
		while(!aGo)  //为何不用if???
		{
			//A 不能运行,等待
			this.wait();
		}
		for(int i=0;i<10;i++)
		{
			System.out.println("AAAAA--------------"+i);
		}
		//运行完之后,将aGo切换为FALSE,让B运行
		aGo=false;
		this.notify();//唤醒一个正在等待的线程
	}

	public synchronized void B()throws Exception{
		while(aGo)
		{
			//B 不能运行,等待
			this.wait();
		}
		for(int i=0;i<100;i++)
		{
			System.out.println("B--------------"+i);
		}
		//运行完之后,将aGo切换为true,让A运行
		aGo=true;
		this.notify();//唤醒一个正在等待的线程
	}
}

说明:

1. 如果有大于两个多线程在执行,最好用notifyAll,为什么?

例如,如果本例中多起几个线程,如果此时有A1,B1线程在wait,某个A线程执行完,将aGo置为false,并唤醒正在等待锁的其中一个线程,A1或B1,如果此时正好A1线程抢到了CPU,则A1运行,判断方法A1进入wait状态,而B1由于没有被唤醒,之后继续等待,那么到最后,A1和B1都处于wait状态,造成了死锁。

而如果改为notifyAll的话,A1和B1都被唤醒,抢到锁的线程先执行,如果A1抢到的话,继续等待,然后B1继续执行,因为此时aGo=false,所以B1执行,将aGo=true,A1继续执行完毕。

结论:只要A和B启动的线程的个数不同,就可能造成死锁的情况。

2.
判断aGo的地方为什么要使用while,if不行吗?在wait方法说明中,也推荐使用while,因为在某些特定的情况下,线程有可能被假唤醒,使用while会循环检测更稳妥。在本例中,A和B应该是交替运行的,但是如果多启动几个线程,如果有A1线程在等待(wait)状态,而A2线程执行完毕,aGo设置为false,唤醒正在等待的线程(可能是A也可能是B),如果是A被唤醒的话,如果用了if而不是while,那么A执行,这样A就连续执行了两遍,不符合我们的设计要求,但如果换用while的话,即使A被唤醒,他会再次判断aGo的值,发现是false,则继续等待。直到B线程将其唤醒。

时间: 2024-10-09 21:59:30

Java多线程与并发应用-(4)-传统线程通信技术试题的相关文章

2020年Java多线程与并发系列22道高频面试题(附思维导图和答案解析)

前言 现在不管是大公司还是小公司,去面试都会问到多线程与并发编程的知识,大家面试的时候这方面的知识一定要提前做好储备. 关于多线程与并发的知识总结了一个思维导图,分享给大家 1.Java中实现多线程有几种方法 (1)继承Thread类: (2)实现Runnable接口: (3)实现Callable接口通过FutureTask包装器来创建Thread线程: (4)使用ExecutorService.Callable.Future实现有返回结果的多线程(也就是使用了ExecutorService来管

Java多线程与并发——死锁与中断线程

过多的同步有可能出现死锁,死锁的操作一般是在程序运行的时候才有可能出现. 多线程中要进行资源的共享,就需要同步,但同步过多,就可能造成死锁. 死锁例子: package com.vince; /** * 线程死锁 * @author acer * */ public class DeadThreadDemo { public static void main(String[] args) { new DeadThread(); } } //顾客 class Customer{ public sy

Java多线程与并发库高级应用-线程池

线程池 线程池的思想  线程池的概念与Executors类的应用 > 创建固定大小的线程池 > 创建缓存线程池 > 创建单一线程池(如何实现线程死掉后重新启动?) 关闭线程池 > shutdown 与 shutdownNow的比较 用线程池启动定时器 > 调用ScheduleExecutorService 的 schedule 方法,返回的ScheduleFuture对象可以取消任务. > 支持间隔重复任务的定时方式,不直接支持决定定时的方法,需要转换成相对时间方式.

Java多线程与并发库高级应用之线程数据交换Exchanger

JDK1.5提供了Exchanger用于两个线程的数据交换.两个线程先后到达交换点,先到达的线程会等待后到达的线程,然后两个线程互相交换数据,交换后双方持对方的数据. Exchanger只提供了一个构造器: Exchanger():创建一个新的Exchanger. Exchanger中也只有两个方法: V exchange(V x): 等待另一个线程到达此交换点(除非当前线程被中断),然后将给定的对象传送给该线程,并接收该线程的对象. V exchange(V x, long timeout,

Java多线程与并发---学习总结(很详细)

Java多线程与并发---学习总结(很详细) 1.      计算机系统 使用高速缓存来作为内存与处理器之间的缓冲,将运算需要用到的数据复制到缓存中,让计算能快速进行:当运算结束后再从缓存同步回内存之中,这样处理器就无需等待缓慢的内存读写了. 缓存一致性:多处理器系统中,因为共享同一主内存,当多个处理器的运算任务都设计到同一块内存区域时,将可能导致各自的缓存数据不一致的情况,则同步回主内存时需要遵循一些协议. 乱序执行优化:为了使得处理器内部的运算单位能尽量被充分利用. 2.      JAVA

JAVA多线程和并发基础面试问答(转载)

原文链接:http://www.cnblogs.com/dolphin0520/p/3932934.html 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一.在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对应日后碰到的问题. Java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用.而线程是在进程中执行的一个任务.Java运行环境是一个包含

JAVA多线程和并发基础面试问答

原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-answers/ 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一.在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对应日后碰到的问题.(校对注:非常赞同这个观点) Java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环

JAVA多线程和并发基础面试问答【转】

JAVA多线程和并发基础面试问答 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一.在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对应日后碰到的问题.(校对注:非常赞同这个观点) Java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用.而线程是在进程中执行的一个任务.Java运行环境是一个包含了不同的类和程序的单 一进程.线程可以被称为轻量

JAVA 多线程和并发学习笔记(三)

Java并发编程中使用Executors类创建和管理线程的用法 1.类 Executors Executors类可以看做一个“工具类”.援引JDK1.6 API中的介绍: 此包中所定义的 Executor.ExecutorService.ScheduledExecutorService.ThreadFactory 和 Callable 类的工厂和实用方法.此类支持以下各种方法: 创建并返回设置有常用配置字符串的 ExecutorService 的方法. 创建并返回设置有常用配置字符串的 Sche