码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2015-04-14 23:25:54      阅读:180      评论:0      收藏:0      [点我收藏+]

标签:多线程   并发   java   线程安全   thread   

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线程将其唤醒。

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

标签:多线程   并发   java   线程安全   thread   

原文地址:http://blog.csdn.net/lp1137917045/article/details/45047763

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!