/*
* 線程間通訊:-解決安全問題
* 其實就是多個線程在操作同一個資源
* 但是操作的動作不同
*/
/*【用舉例的思路註解】
* 【1】編寫完畢,
* 【2】運行我們發現,小煥煥的性別一會女一會man, 是線程出現了安全漏洞
* 接下來,我們封堵上這個漏洞。採用同步
* 想到2個前提,
* 同步的前提
* 1、必須有2個以上的線程 【a】【b】
* 2、必須是一個鎖
* 我們先用的是obj 發現不是同一個,然後用了this 也不是,那麼該程序在內存總有一個是唯一的
* 發現,內存裏有4個類,類名.class 然後我們繼續看,這個程序裏,還有一個對象是唯一的
* 那就是主函數中的【r】。
* 【3】搞定以後,我們發現,按道理應該是存一個打印一個纔對。
* 【等待喚醒機制】 wait();等待 notify();喚醒 notifyAll();全部喚醒 都必須有監視器,就是鎖
*
* 這三個方法,都使用在同步中,因爲要持有監視器(鎖)的線程操作,
* 所以要使用在同步中,因爲只有同步才具有監視器(鎖)的感念
*
* 爲什麼這些操作線程的方法要定義在Object類中呢?
* 因爲這些 方法在操作同步中線程時,都必須要表示他們所操作線程持有的鎖
* 只有同一個鎖上的被等待線程,可以被同一個鎖上的notify喚醒
* 不可以對不同鎖中的線程進行喚醒
*
* 也就是說:等待和喚醒必須是同一個鎖
*
* 而鎖可以是任意對象,所以可以被任意對象調用的方法定義在Object中
*/
//設計一個煤礦堆
class Res{
String name;
String set;
boolean falg = false;
}
//設計一個進貨的貨車
class Input implements Runnable{
private Res r;
Input(Res r){
this.r=r;
}
Object obj=new Object();
public void run(){
int x=0;
while(true){
synchronized(r){//【a】
if(r.falg)
try{r.wait();}
catch(Exception e){}
if(x==0){
r.name="Yunyao";
r.set="man";
}
else{
r.name="小煥煥";
r.set="女";
}
x=(x+1)%2;
r.falg=true;
r.notify();
}
}
}
}
//設計一個拉貨的貨車
class Output implements Runnable{
private Res r;
Output(Res r){
this.r=r;
}
Object obj=new Object();
public void run(){
//int x=0;
while(true){
synchronized(r){//【b】
if(!r.falg)
try{r.wait();}catch(Exception e){}
System.out.println(r.name+"..."+r.set+"...");
//x+=1;
r.falg=false;
r.notify();
}
}
}
}
public class D_Th_InputOutpt {
public static void main(String[] args) {
Res r=new Res();//創建一個煤礦堆
程序中唯一的一個對象。
Input in = new Input(r); //創建一個進貨的車
Output ot = new Output(r);//創建一個出貨的車
Thread t1 = new Thread(in);//進入高速通道
Thread t2 = new Thread(ot);
t1.start();// 開始跑起走
t2.start();
}
}
--------------------------------------------------------------------------------------------------------
優化一
package _Day12;
/*
* 對前一個問題進行優化。
*/
//設計一個煤礦堆
class Res1{
private String name;
private String set;
boolean falg = false;
//同步函數 非靜態同步函數 用的鎖是 this ,記住了。
public synchronized void setInfo(String name,String set){
if(falg)
try{this.wait();}catch(Exception e){}
this.name=name;
this.set=set;
this.falg=true;
this.notify();
}
public synchronized void showInfo(){
if(!falg)
try{this.wait();}catch(Exception e){}
System.out.println(this.name+"..."+this.set);
this.falg=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.setInfo("fei", "man");
else
r.setInfo("小煥煥", "女女女女女");
x=(x+1)%2;
}
}
}
//設計一個拉貨的貨車
class Output1 implements Runnable{
private Res1 r;
Output1(Res1 r){
this.r=r;
}
public void run(){
while(true){
r.showInfo();
}
}
}
public class D_Th_YouhuaInOut {
public static void main(String[] args) {
Res1 r=new Res1();//創建一個煤礦堆
new Thread(new Input1(r)).start();
new Thread(new Output1(r)).start();
/* 六句優化成上面兩句【 匿名對象形式】
Input1 in = new Input1(r); //創建一個進貨的車
Output1 ot = new Output1(r);//創建一個出貨的車
Thread t1 = new Thread(in);//進入高速通道
Thread t2 = new Thread(ot);
t1.start();// 開始跑起走
t2.start();
*/
}
}
---------------------------------------------------------------------------------------------
/*
* 線程間通信--生產者消費者
*/
/*當生產和消費是單線程的時候沒有問題,下面我們把兩條線都加一倍試試
發現有問題,經判斷是因爲線程被喚醒後沒有對falg再次進行判斷,
因爲if只執行一次,現在,我們把if替換成while試試
發現4個線程出現了同時等待。。。。
notify喚醒的是線程池中第一個被等待的線程,很有可能就是本方的,
導致所有線程等待,從而數據錯亂
而使用while 則容易出現線程全部出現同時等待的現象。
所以必須使用:notifyAll 全部喚醒
因爲有while,所以都會循環去判斷標記,進入循環漸進的生成消費。
【自我總結】【注意:1.5以前版本使用】升級1.5里程碑版本的時候改
成了5.0具體【【【LOCK】】】優化synchronized 請看D_Th_Lock
當有多條線程時候,必須要使用while,notifyAll
while 必須去判斷標記,是不是在標記允許範圍內做動作
notifyAll 要把對方喚醒,
*/
public class D_Th_YouhuaInOut2 {
public static void main(String []args){
Resource r=new Resource();
new Thread(new Shengc(r)).start();
new Thread(new Shengc(r)).start();
new Thread(new Xiaof(r)).start();
new Thread(new Xiaof(r)).start();
Shengc sc=new Shengc(r);
Xiaof xf=new Xiaof(r);
/*
Thread t1=new Thread(sc);
Thread t2=new Thread(xf);
Thread t3=new Thread(sc);
Thread t4=new Thread(xf);
t1.start();
t2.start();
t3.start();
t4.start();
*/
}
}
class Resource{
private String name;
private int count=1;
private boolean falg=false;
public synchronized void set(String name){
while(falg)
try{this.wait();}catch(Exception e){}
this.name=name+"..."+count++;
System.out.println(Thread.currentThread().getName()+"..生產.."+this.name);
this.falg=true;
this.notifyAll();
}
public synchronized void get(){
while(!falg)
try{this.wait();}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"-----消費----"+this.name);
this.falg=false;
this.notifyAll();
}
}
class Shengc implements Runnable{
private Resource r;
Shengc(Resource r){
this.r=r;
}
public void run(){
int x=0;
while(true){
r.set("+商品+");
}
}
}
class Xiaof implements Runnable{
private Resource r;
Xiaof(Resource r){
this.r=r;
}
public void run(){
while(true){
r.get();//r.outInfo();
}
}
}
/*
public synchronized void setInfo(String name){
if(falg)
try{this.wait();}catch(Exception e){}
this.name=name+"..."+count++;
this.falg=true;
this.notify();
}
public synchronized void outInfo(){
if(!falg)
try{this.wait();}catch(Exception e){}
System.out.println(this.name);
this.falg=false;
this.notify();
}
*/
/*
if(x==0)
r.setInfo("脈動");
else
r.setInfo("哇哈哈");
x=(x+1)%2;
*/
---------- android培訓、 java培訓 、期待與您交流!----------
黑馬官網: http://edu.csdn.net/heima