Java基礎第十二天學習日記_線程、線程的同步、線程間通訊

------- android培訓java培訓、期待與您交流! ----------

線程間通信:其實就是多個線程在操作同一個資源,但是操作的動作不同。

思考的問題:1.wait(),notify(),notifyAll(),用來操作線程爲什麼定義在了Object類中?

  答:1、這些方法存在於同步中。

         2、使用這些方法時必須要標識所屬的同步的鎖。只有同一個鎖上的被等待線程,可以被同一個鎖的notify喚醒。不可以對不同鎖中的線程進行喚醒。也就是說,等待和喚醒必須是同一個鎖。

         3、鎖可以是任意對象,所以任意對象調用的方法一定定義在Object類中。

2、wait()、sleep()有什麼區別?

  答:wait():釋放資源,釋放鎖。

         sleep():釋放資源,不釋放鎖。

等待喚醒機制:

等待的線程都會保存在內存的線程池中,喚醒時,如無特殊的說明,喚醒的就是線程池中第一個等待的線程。

public class InputOutputDemo 
{
	public static void main(String[] args) 
	{
		Res r=new Res();
		Input in=new Input(r);
		Output out=new Output(r);
		Thread t1=new Thread(in);
		Thread t2=new Thread(out);
		t1.start();
		t2.start();
	}
}
class Res
{
	String name;
	String sex;
	boolean flag=false;
}
class Input implements Runnable
{
	private Res r;
	Input(Res r)
	{
		this.r=r;
	}
	public void run()
	{
		int x=0;
		while(true)
		{
			synchronized(r)
			{
				if(r.flag)
					try{r.wait();}catch(Exception e){}//wait和notify方法必須標明是那個鎖對象,這樣才能明白要等待喚醒哪個線程。
				if (x==0)
				{
					r.name="zhangsan";
					r.sex="man";
				}
				else
				{
					r.name="lisi";
					r.sex="woman";
				}
				x=(x+1)%2;
				r.flag=true;
				try{r.notify();}catch(Exception e){}
			}
		}	
	}
}
class Output implements Runnable
{
	private Res r;
	Output(Res r)
	{
		this.r=r;
	}
	public void run()
	{
		while(true)
		{
			synchronized (r)
			{
				if(!r.flag)
					try{r.wait();}catch(Exception e){}
				System.out.println(r.name+"-----"+r.sex);
				r.flag=false;
				try{r.notify();}catch(Exception e){}
			}
		}
	}
}
public class InputOutputDemo2 
{
	public static void main(String[] args) 
	{
		Res1 r=new Res1();
		Thread t1=new Thread(new Input1(r));
		Thread t2=new Thread(new Output1(r));
		t1.start();
		t2.start();
		
	}
}
class Res1
{
	private String name;
	private String sex;
	private boolean flag=false;
	public synchronized void set(String name,String sex)
	{
		if(flag)
			try{this.wait();}catch(InterruptedException e){}
		this.name=name;
		this.sex=sex;
		flag=true;
		this.notify();
	}
	public synchronized void out()
	{
		if(!flag)
			try{this.wait();}catch(InterruptedException e){}
		System.out.println(name+"-----"+sex);
		flag=false;
		this.notify();
	}
}
class Input1 implements Runnable
{
	private Res1 r;
	Input1(Res1 r)
	{
		this.r=r;
	}
	public void run()
	{
		int x=0;
		while(true)
		{
			if(x==0)
				r.set("zhangsan","man");
			else
				r.set("lisi","woman");
			x=(x+1)%2;
		}
	}
}
class Output1 implements Runnable
{
	private Res1 r;
	Output1(Res1 r)
	{
		this.r=r;
	}
	public void run()
	{
		while(true)
		{
			r.out();
		}
	}
}

 

JD1.5中提供了多線程升級解決方案。將同步Synchronized替換成實現Lock操作。將Object中的wait,notify,notifyAll,替換成了condition對象。該對象可以Lock鎖進行獲取。

package day12;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ProducerCustomerDemo2 
{
		public static void main(String[] args)
		{
			Resource1 r=new Resource1();
			Producer1 p=new Producer1(r);
			Customer1 c=new Customer1(r);
			Thread t1=new Thread(p);
			Thread t2=new Thread(p);
			Thread t3=new Thread(c);
			Thread t4=new Thread(c);
			t1.start();
			t2.start();
			t3.start();
			t4.start();
		}
}
class Resource1
{
	private String name;
	private int count;
	private boolean flag=false;
	private Lock lock=new ReentrantLock();//1.5版本新特性。相當與synchronized語句。
	//private Condition condition=lock.newCondition();//Condition相當與監視器方法,由lock的newCondition()方法獲取。
	private Condition condition_pro=lock.newCondition();//每個lock可以建立多個condition,它們可以互相等待喚醒。
	private Condition condition_cus=lock.newCondition();
	public void set(String name)throws InterruptedException
	{
		lock.lock();//上鎖
		try
		{
			while(flag)
				condition_pro.await();//由await()替換wait()方法
			this.name=name+"----"+count++;
			System.out.println(Thread.currentThread().getName()+"...生產者。。。"+this.name);
			flag=true;
			condition_cus.signal();//由signal()替換notify(),由signalAll()替換notifyAll()
		}
		finally
		{
			lock.unlock();
		}
	} 
	public void out()throws InterruptedException
	{
		lock.lock();
		try
		{
			while(!flag)
				condition_cus.await();
			System.out.println(Thread.currentThread().getName()+"...消費者。。。。。。。。"+this.name);
			flag=false;
			condition_pro.signal();
		}
		finally
		{
			lock.unlock();
		}
	}
}
class Producer1 implements Runnable
{
	private Resource1 r;
	Producer1(Resource1 r)
	{
		this.r=r;
	}
	public void run()
	{
		while(true)
		{
			try
			{
				r.set("商品");
			}
			catch(InterruptedException e){}
		}
	}
}
class Customer1 implements Runnable
{
	private Resource1 r;
	Customer1(Resource1 r)
	{
		this.r=r;
	}
	public void run()
	{
		while(true)
		{
			try
			{
				r.out();
			}
			catch(InterruptedException e){}
		}
	}
}

停止線程:

1、定義循環結束標記

因爲線程運行代碼一般都是循環,只要控制了循環即可。

2、使用interrupt(中斷)方法。

該方法是結束線程的凍結狀態,使線程回到運行狀態中來。

public class InterruptDemo {

	/**
	 * 線程的終止	
	 */
	public static void main(String[] args)
	{
		StopThread st=new StopThread();     
		Thread t1=new Thread(st);
		Thread t2=new Thread(st);                                                                                        
		t1.start();
		t2.start();
		int num=0;
		while(true)
		{
			if(num++==60)
			{
				t1.interrupt();//中斷線程的凍結狀態。跟notify/signal的區別是這是強制中斷的,中斷後拋出異常。
				t2.interrupt();
				break;
			}
			System.out.println(Thread.currentThread().getName()+"...."+num);
		}	
	}
}
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");
		}
	}
}

一些有用的方法:

1、setDaemon(boolean)該線程標記爲守護線程或用戶線程。當正在運行的線程都是守護線程時,Java虛擬機退出。該方法必須在分啓動線程前調用。前臺線程一結束,則守護線程也結束。

2、join()等待該線程終止。當A線程執行到了B線程的join()方法時,A就會等待。等B線程都執行完,A纔會執行。join可以用來臨時加入線程執行。

3、toString打印出當前線程的字符串表示形式,也就是更加詳細的信息,有線程名稱,線程優先級,線程所屬的線程組。一般誰開啓了這個線程,那麼這個線程便屬於那個線程組。

優先級表示cpu的執行頻率,優先級越大執行頻率越高。

4、setPriority(Thread.MAX_PRIORITY);設置線程的優先級(1-10)。

5、yield();暫停當前正在執行的線程對象,並執行其他線程。

------- android培訓java培訓、期待與您交流! ----------  詳細請查看:http://edu.csdn.net/heima/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章