12-24java面向對象之同步和死鎖

案例1

設計一個線程操作類,要求可以產生三個線程對象,並可以設置三個線程的休眠時間

分析:

1.使用Thread類實現

class MyThread extends Thread
{
	//封裝屬性
	private String name ;		//定義該線程的名稱
	private int time;			//定義休眠時間
	//構造方法
	public MyThread(String name , int time)
	{
		super(name);
		this.time = time;
	}
	//覆寫run方法
	public void run()
	{
		System.out.println(Thread.currentThread().getName() + "休眠開始");
		try
		{
			Thread.currentThread().sleep(this.time);
		}
		catch (InterruptedException e)
		{
			System.out.println(Thread.currentThread().getName() +"休眠中斷");
		}
		System.out.println(Thread.currentThread().getName() + "休眠結束" + "持續:" + this.time + "ms");
	}
}
public class TestThread16
{
	public static void main(String[] args)
	{
		MyThread mt1 = new MyThread("線程A",1000);
		mt1.start();
		MyThread mt2 = new MyThread("線程B",2000);
		mt2.start();
		MyThread mt3 = new MyThread("線程C",3000);
		mt3.start();
	}
}

1.使用Runnable接口實現

class MyThread implements Runnable
{
	//封裝屬性
	private String name ;
	private int time ;
	//構造方法
	public MyThread(String name , int time)
	{
		this.name = name ;
		this.time = time ;
	}
	public String getName()
	{
		return this.name ;
	}
	//覆寫run方法
	public void run()
	{
		System.out.println(this.name + "休眠開始");
		try
		{
			Thread.currentThread().sleep(this.time);
		}
		catch (InterruptedException e)
		{
			System.out.println(this.name +"休眠中斷");
		}
		System.out.println(this.name + "休眠結束" + "持續:" + this.time + "ms");
	}
}
public class TestThread17
{
	public static void main(String[] args)
	{
		MyThread mt1 = new MyThread("線程A",1000);
		new Thread(mt1).start() ;
		MyThread mt2 = new MyThread("線程B",2000);
		new Thread(mt2).start() ;
		MyThread mt3 = new MyThread("線程C",3000);
		new Thread(mt3).start() ;
	}
}

同步

問題的引出:把各個售票點理解爲線程,那麼各個線程需要共享資源。如果引入延時,系統可能存在負數的問題。

class Sale implements Runnable
{
	private int ticket = 5;
	public void run()
	{
		for (int i =0;i<50 ; ++i )
		{
			if (ticket>0)
			{
				System.out.println("買票成功,還剩下票數 ticcket=" + ticket--);
			}
		}
	}
}
public class TestChronized1 
{
	public static void main(String[] args) 
	{
		Sale s = new Sale();
		Thread th1 = new Thread(s);
		Thread th2 = new Thread(s);
		Thread th3 = new Thread(s);
		th1.start();
		th2.start();
		th3.start();
	}
}

下面引入延時

class Sale implements Runnable
{
	private int ticket = 5;
	public void run()
	{
		for (int i =0;i<50 ; ++i )
		{
			if (ticket>0)
			{
				try
				{
					Thread.sleep(500);
				}
				catch (InterruptedException e)
				{
					e.printStackTrace();
				}
				System.out.println("買票成功,還剩下票數 ticcket=" + ticket--);
			}
		}
	}
}
public class TestChronized1 
{
	public static void main(String[] args) 
	{
		Sale s = new Sale();
		Thread th1 = new Thread(s);
		Thread th2 = new Thread(s);
		Thread th3 = new Thread(s);
		th1.start();
		th2.start();
		th3.start();
	}
}

結果


要想解決數據共享問題——使用同步代碼塊或同法方法。

同步代碼塊

class Sale implements Runnable
{
	private int ticket = 5;
	public void run()
	{
		for (int i =0;i<50 ; ++i )
		{
			synchronized (this)
			{
				if (ticket>0)
				{
					try
					{
						Thread.sleep(500);
					}
					catch (InterruptedException e)
					{
						e.printStackTrace();
					}
					System.out.println("買票成功,還剩下票數 ticcket=" + ticket--);
				}
			}			
		}
	}
}
public class TestChronized2 
{
	public static void main(String[] args) 
	{
		Sale s = new Sale();
		Thread th1 = new Thread(s);
		Thread th2 = new Thread(s);
		Thread th3 = new Thread(s);
		th1.start();
		th2.start();
		th3.start();
	}
}

 同步代碼塊:

Synchronized (同步對象){}

其中同步對象一般使用this代替

 

同步方法

class Sale implements Runnable
{
	private int ticket = 5;
	public void run()
	{
		for (int i =0;i<50 ; ++i )
		{		
			saleTicket();
		}
	}
	public synchronized void saleTicket()
	{
		if (ticket>0)
			{
				try
				{
					Thread.sleep(500);
				}
				catch (InterruptedException e)
				{
					e.printStackTrace();
				}
				System.out.println("買票成功,還剩下票數 ticcket=" + ticket--);
			}		
	}
}
public class TestChronized3 
{
	public static void main(String[] args) 
	{
		Sale s = new Sale();
		Thread th1 = new Thread(s);
		Thread th2 = new Thread(s);
		Thread th3 = new Thread(s);
		th1.start();
		th2.start();
		th3.start();
	}
}

結果完全相同

Synchronized 方法返回值  方法()  {}

死鎖

不同的線程在互相等待

總結:

只要數據共享就需要同步

過分同步就會產生死鎖

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章