黑马程序员---Java基础学习笔记(多线程-后篇)

------------Android培训 、Java培训、期待与您交流----------

1.wait()、sleep()、notify()、notifyAll()方法
    wait():使一个线程处于等待状态,并且释放所持有的对象的lock。 
    sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException异常。 
    notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程(一般是最先开始等待的线                程),而且不是按优先级。 
    notifyAll():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争。

    为什么wait()、notify()、notifyAll()这些用来操作线程的方法定义在Object类中?
    (1)这些方法只存在于同步中;
    (2)使用这些方法时必须要指定所属的锁,即被哪个锁调用这些方法;
    (3)而锁可以是任意对象,所以任意对象调用的方法就定义在Object中。
class StopThread implements Runnable
{
	private boolean flag = true;
	public synchronized void run()
	{
		while(flag)
		{
			try 
			{
				wait();//线程冻结
			} 
			catch (InterruptedException e) 
			{
				System.out.println(Thread.currentThread().getName()+"...Exception");
				flag = false;
			}
			System.out.println(Thread.currentThread().getName()+"...run");
		}
	}
	/*
	public void changeF()
	{
		flag = false;
	}
	*/
}
/*
 * 主线程是前台线程,主线程一结束,其他线程自动就结束了。
 */
public class ThreadStop 
{
	public static void main(String[] args)
	{
		StopThread st= new StopThread();
		Thread t1 = new Thread(st);
		Thread t2 = new Thread(st);
		
		t1.setDaemon(true);//守护线程(必须在启动线程前调用)
		t2.setDaemon(true);
		t1.start();
		t2.start();
		
		int i = 0;
		while(true)
		{
			if(i++ == 60)
			{
				//st.changeF();
				//t1.interrupt();//强制恢复线程
				//t2.interrupt();
				break;
			}
			System.out.println(Thread.currentThread().getName()+"......"+i);
		}
		System.out.println(Thread.currentThread().getName()+"...over...");
	}
}

2.多个窗口同时卖票问题

创建线程的第二个方法:实现Runnable()接口(最为常用的方法)
 步骤:  
 1.定义一个类实现Runnable()接口
2.覆盖Runnable()接口中的run方法将线程要运行的代码放在run方法中
3.通过Thread类建立线程对象
4.将Runnable()接口的子类对象作为实际参数传递给Thread类的构造函数为什么要将Runnable()接口的子类对象传递给Thread类的构造函数?
                         因为自定义的run方法所属的对象是Runnable()接口的子类对象。所以要让线程去执行指定对象的run方法
5.调用Thread类的start方法开启线程并调用

 P.S.实现Runnable()方式和继承方式有什么区别?
 前者避免了java单继承的局限性问题,在定义线程时建议使用implements实现方式。
 区别:
extends Thread 线程的代码存放在Thread子类的run方法中
implements Runnable 线程代码存放在接口的子类的run方法中

class TicketThread implements Runnable//extends Thread
{
	private /*static第一种方式中实现使用*/ int ticket = 100;
	//Object obj = new Object();
	public void run()
	{
		while(true)
		{
			//synchronized(obj)锁 
			if(ticket>0)
			{
				/*通过分析发现结果因此出现负数票结果,导致多线程出现了安全问题
				 * 原因:当多条语句在操作同一个线程共享数据资源时,一个线程对多条语句
				 * 只执行了一部分尚未执行完,另一个线程就参与进来,导致共享数据的错误
				 * 解决法:对多条操作共享数据的线程在某一时间段只能允许一个线程执行,此过程中
				 * 其他线程不可参与运行。
				 * java对于多线程的安全问题提供了'同步代码块'
				 * synchronized(Object obj)
				 * {
				 * 		需要同步的代码(操作共享数据的语句);
				 * 		if(ticket>0)
						{
							try
							{
								Thread.sleep(10);
							}
							catch (Exception e) 
							{
								// TODO: handle exception对异常未做处理
							}
							System.out.println(Thread.currentThread().getName()+ " sold..."+ticket-- );
						}
				 	}
				 	同步的前提:1.必须要有两个或者两个以上的线程
				 			   2.必须是多个线程使用同一个锁
				 	必须保证同步中只有一个线程在运行
				 	弊端:因为每个线程每次都要判断锁的状态,占用并消耗了较多的系统资源,程序运行会比较慢。
				 */
				/* 
				try 
				{
					Thread.sleep(10);
				} 
				catch (Exception e) 
				{
					// TODO: handle exception对异常未做处理
				}
				*/
				System.out.println(Thread.currentThread().getName()+ " sold..."+ticket-- );
			}
		}
	}
}

public class TicketSell
{
	public static void main(String[] args) 
	{	
		TicketThread t = new TicketThread();
		
		Thread t1 = new Thread(t);//指定run方法所属对象t
		Thread t2 = new Thread(t);
		Thread t3 = new Thread(t);
		Thread t4 = new Thread(t);
		
		t1.start();//调用的是Thread中的run方法
		t2.start();
		t3.start();
		t4.start();
	}
}
------------Android培训 、Java培训、期待与您交流----------


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值