您的位置:首页 > 职场人生

黑马程序员——12,多线程(2)

2015-07-29 00:31 603 查看
------<ahref="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------黑马程序员——12,多线程(2)
//线程之间的通信
//就是多个线程操作同一个资源,操作动作不同
//举一个例子:一堆资源(名字,性别),一个线程输入,一个线程输出打印

class  Person
{
String  name;
String  sex;
}

class   Shuru  implements  Runnable
{
private  Person  p;
Shuru( Person p   )
{
this.p=p;
}
public  void  run()
{
int x= 0;
while(true)//特别说明:因为 while (true)这句话的关系,最后要按Ctrl+c按键才停下虚拟机,否则会耗费很多资源)
{
if(x==0)
{
p.name="张三";
p.sex="男性";
}
else
{
p.name="李四";
p.sex="女性";
}
x=(x+1)%2;
}
}
}
class  Shuchu  implements  Runnable
{
private Person  p;
Shuchu( Person  p   )
{
this.p=p;
}
public  void  run()
{
while(true)
{
System.out.println(p.name+"-----"+p.sex);
}
}

}

class Xctx
{
public  static  void  main(String[] args)
{
Person  p=new Person();

Shuru  b1=new Shuru(p);
Shuchu  b2=new Shuchu(p);

Thread  c1=new Thread(b1);
Thread  c2=new Thread(b2);

c1.start();
c2.start();
System.out.println("HelloWorld!");
}
}

/*
按照一般的思路,准确的打印应该是张三对应男性,李四对应女性的
可是编译运行的结果如下,出了问题:
Hello World!
李四-----男性
李四-----男性
李四-----女性
李四-----男性
张三-----女性
张三-----女性
李四-----男性
李四-----男性
张三-----男性
张三-----女性
张三-----男性
张三-----男性
李四-----男性
张三-----男性
李四-----女性
李四-----男性
张三-----男性
李四-----女性
张三-----女性
李四-----女性
李四-----男性

出问题的原因是:输入线程在输入信息的同时输出线程也在打印,
那么很有可能在输入信息输入到一半的时候,就被输出线程打印出去了,
那么打印出去的就是部分更新数据部分旧数据,这就对应不上了
*/
——————分析——————
//为了解决这种问题,我们还是可以用同步代码块来解决
/*
原理就是输入线程与输出线程都是对同一个对象操作,只不过操作过程不一样
那么使用同步代码块,让两个使用同一个锁,这样就限制了在某一个时刻只能够有一个线程对对象进行操作
等这个线程操作完之后下一个线程才可以对对象进行操作
确保了打印出来的对象信息的更新是完整
*/

class  Person
{
String  name;
String  sex;
static  Object obj=new Object();
}

class   Shuru  implements Runnable
{
private  Person  p;
Shuru( Person p   )
{
this.p=p;
}
public  void run()
{
int x= 0;
while(true)//特别说明:因为 while (true)这句话的关系,最后要按Ctrl+c按键才停下虚拟机,否则会耗费很多资源)

{
synchronized(Person.obj)//用的锁是obj
{
if(x==0)
{
p.name="张三";
p.sex="男性";
}
else
{
p.name="李四";
p.sex="女性";
}
x=(x+1)%2;
}
}
}

}
class   Shuchu  implements  Runnable
{
private  Person   p;
Shuchu( Person  p   )
{
this.p=p;
}
public void run()
{
while(true)
{
synchronized(Person.obj)//用的锁是obj
{
System.out.println(p.name+"-----"+p.sex);
}
}
}

}

class  Xctx2
{
public  static  void  main(String[] args)
{
Person  p=new Person();

Shuru  b1=new Shuru(p);
Shuchu  b2=new Shuchu(p);

Thread  c1=new Thread(b1);
Thread  c2=new Thread(b2);

c1.start();
c2.start();
System.out.println("HelloWorld!");
}
}
——————分析——————
</pre><pre name="code" class="java">//线程通信中的等待唤醒机制的例子

/*
等待唤醒机制,简单的说法就是
用一个标示(一般是Boolean型的变量)
true标记输入线程操作,而false标记输出线程操作
输入线程操作时候,输出线程冻结状态
输出线程操作时候,输入线程冻结状态
这样来保证输出结果的准确性
这就需要用到wait()和notify()  或者是notifyAll()
*/
class  Person
{
String  name;
String  sex;
static  Object obj=new Object();
boolean  bs=true;//设定一个标示
}

class   Shuru  implements Runnable
{
private  Person  p;
Shuru( Person p   )
{
this.p=p;//接收一个Person类的对象,就指向该对象,该写法更加方便
}
public  void  run()
{
int x= 0;
while(true)
//特别说明:因为 while (true)这句话的关系,最后要按Ctrl+c按键才停下虚拟机,否则会耗费很多资源)

{
synchronized(Person.obj)//用的锁是obj
{
if(!p.bs)
{
try{Person.obj.wait();}catch(Exception e){}
}
//wait()方法可以冻结线程,该方法是定义在Object类的
/*
这里为什么不直接用wait()呢?
因为wait()方法会抛出一个异常所以要用try...catch
为什么这里还要在wait前面加上Person.obj这个锁呢?
因为这种写法:锁.wait();   -----表示持有该锁的线程要陷入沉睡。
也是因为这个原因,wait()方法必须在同步中才可以用,而notify()
和notifyAll()也是因为以上原因在同步中才可以用。
其写法也是:  锁.notify();或者是  锁.notifyAll();

*/
if(x==0)
{
p.name="张三";
p.sex="男性";
}
else
{
p.name="李四";
p.sex="女性";
}
x=(x+1)%2;
Person.obj.notify();
/*
陷入沉睡的线程都会被扔进线程池
notify()方法功能是唤醒在在线程池中头一个沉睡的线程
而notifyAll()方法则是唤醒所有沉睡的线程
*/
p.bs=false;
}
}
}

}
class   Shuchu  implements  Runnable
{
private  Person   p;
Shuchu( Person  p   )
{
this.p=p;
}
public  void  run()
{
while(true)
{
synchronized(Person.obj)//用的锁是obj
{
if(p.bs)
{
try{Person.obj.wait();} catch(Exception e){}
}

System.out.println(p.name+"-----"+p.sex);
Person.obj.notify();
p.bs=true;
}
}
}

}

class Xctx3
{
public  static void main(String[] args)
{
Person  p=new Person();

Shuru  b1=new Shuru(p);
Shuchu  b2=new Shuchu(p);

Thread  c1=new Thread(b1);
Thread  c2=new Thread(b2);

c1.start();
c2.start();
System.out.println("HelloWorld!");
}
}
/*
以上程序编译运行结果是:
Hello World!
张三-----男性
李四-----女性
张三-----男性
李四-----女性
张三-----男性
李四-----女性
张三-----男性
李四-----女性
张三-----男性
李四-----女性
张三-----男性
李四-----女性
张三-----男性
李四-----女性

*/
补充:对于非静态的synchronized方法,其锁默认为this对于静态的synchronized方法,其锁默认:为该方法所在类的类名.class对于同步代码块,其锁就是括号内的东西。——————分割线————————
//以下是代码优化之后的程序,更加简洁明了class  Person{private  String  name;private  String  sex;private  boolean  bs=true;//设定一个标示public  synchronized  void  set( String name,String  sex   )//写入资料的方法{if(!bs){try{this.wait();}catch(Exception e){}}this.name=name;this.sex=sex;bs=false;this.notify();}public  synchronized  void  out()//打印资料的方法{if(bs){try{this.wait();}catch(Exception e){}}System.out.println("输出的是----"+name+"---"+sex);bs=true;this.notify();}}class   Shuru  implements  Runnable{private  Person  p;Shuru( Person p   ){this.p=p;}public  void  run(){int x= 0;while(true)//特别说明:因为 while (true)这句话的关系,最后要按Ctrl+c按键才停下虚拟机,否则会耗费很多资源){if(x==0)p.set("张三","男性");elsep.set("李四","女性");x=(x+1)%2;}}}class  Shuchu  implements  Runnable{private Person  p;Shuchu( Person  p   ){this.p=p;}public void run(){while(true){p.out();}}}class  Xctx4{public  static  void  main(String[] args){Person  p=new Person();newThread(new Shuru(p)).start();new Thread(new Shuchu(p)).start();System.out.println("HelloWorld!");/*Shuru  b1=new Shuru(p);Shuchu  b2=new Shuchu(p);Thread  c1=new Thread(b1);Thread  c2=new Thread(b2);c1.start();c2.start();System.out.println("HelloWorld!");*/}}
————————分割线——————
/*多线程的常见生活例子有多个生产者生产食品,有多个消费者消化食品每生产一个食品就消费一个食品*/class  Shipin{private  int  sp=0;private   boolean   f=true;public  synchronized  void  shengchang(  ){while(true){while(f==false)//注意这里用的是while所以每次线程从冻结状态醒来都要检查一次f是否是falsetry{this.wait();} catch(Exception e){}sp++;System.out.println("生产者"+Thread.currentThread().getName()+"----"+sp);f=false;this.notifyAll();/*这里用notifyAll()方法就是为了让所有沉睡的线程醒来既唤醒了生产者又唤醒了消费者此时如果f=true那么由于之前的while作用,消费者即使是得到权限(锁)也不能执行只能冻结,所以只有一个生产者可以得到权限执行。此时如果是f=false那么由于之前的while作用,生产者即使是得到权限(锁)也不能执行只能冻结所以只有一个消费者可以得到权限执行。*/}}public  synchronized  void  xiaofei(   ){while(true){while(f==true)try{this.wait();} catch(Exception e){}System.out.println("消费者"+Thread.currentThread().getName()+"----"+sp);f=true;this.notifyAll();}}}class  Shengchangzhe  implements  Runnable{private  Shipin   a ;Shengchangzhe(Shipin   a){this.a=a;}public void run(){a.shengchang();}}class  Xiaofeizhe  implements  Runnable{private  Shipin   a ;Xiaofeizhe(Shipin   a){this.a=a;}public  void run(){a.xiaofei();}}class   Xctx5{public  static  void  main(String[] args){Shipin  a=new Shipin();Shengchangzhe  b1=new Shengchangzhe(a);Shengchangzhe  b2=new Shengchangzhe(a);Xiaofeizhe     b3=new Xiaofeizhe(a);Xiaofeizhe     b4=newXiaofeizhe(a);Thread  t1=new Thread(b1);Thread  t2=new Thread(b2);Thread t3=new Thread(b3);Thread  t4=new Thread(b4);t1.start();t2.start();t3.start();t4.start();System.out.println("HelloWorld!");}}/*以上程序编译运行结果如下:生产者Thread-0----1Hello World!消费者Thread-3----1生产者Thread-1----2消费者Thread-2----2生产者Thread-0----3消费者Thread-3----3生产者Thread-1----4消费者Thread-2----4生产者Thread-0----5消费者Thread-3----5生产者Thread-1----6消费者Thread-2----6生产者Thread-0----7消费者Thread-3----7生产者Thread-1----8消费者Thread-2----8生产者Thread-0----9消费者Thread-3----9生产者Thread-1----10消费者Thread-2----10生产者Thread-0----11消费者Thread-3----11生产者Thread-1----12消费者Thread-2----12生产者Thread-0----13消费者Thread-3----13生产者Thread-1----14消费者Thread-2----14生产者Thread-0----15消费者Thread-3----15生产者Thread-1----16消费者Thread-2----16生产者Thread-0----17消费者Thread-3----17生产者Thread-1----18消费者Thread-2----18生产者Thread-0----19消费者Thread-3----19生产者Thread-1----20消费者Thread-2----20生产者Thread-0----21消费者Thread-3----21生产者Thread-1----22消费者Thread-2----22生产者Thread-0----23消费者Thread-3----23生产者Thread-1----24消费者Thread-2----24生产者Thread-0----25消费者Thread-3----25生产者Thread-1----26消费者Thread-2----26生产者Thread-0----27消费者Thread-3----27生产者Thread-1----28消费者Thread-2----28生产者Thread-0----29消费者Thread-3----29生产者Thread-1----30消费者Thread-2----30生产者Thread-0----31*/
——————分割线————
//另外一个是jdk1.5版本升级后的情况:import java.util.concurrent.locks.*;//这个导入的是后面需要用到的类/*随着jdk1.5版本的升级,一些新的功能也被加入,更加的方便使用者就拿多线程通信的生产者消费者例子来说*/class   Xctx6{public  static  void  main(String[] args){Shipin  a=new Shipin();Shengchangzhe  b1=new Shengchangzhe(a);Xiaofeizhe     b2=new Xiaofeizhe(a);Thread  t1=new Thread(b1);Thread  t2=new Thread(b1);Thread t3=new Thread(b2);Thread  t4=new Thread(b2);t1.start();t2.start();t3.start();t4.start();System.out.println("HelloWorld!");}}class   Shipin{private  int sp=0;private  boolean  f=true;private  Lock   lock=new   ReentrantLock();//将锁作为一个对象了private  Condition  pro= lock.newCondition();private  Condition  con= lock.newCondition();/*Condition将Object监视器(锁)的方法(wait,notify,notifyAll)分解成不同的对象,这是为了便于与Lock组合使用。Lock代替synchronized方法和语句的使用(同步函数和同步代码块)Condition替代了Object监视器(锁)的方法的使用。Condition实例是绑定在锁上的,一个Lock实例要获得Condition实例就要调用newCondition方法。*/public    void  shengchang() throws  InterruptedException{lock.lock();try{while(f==false)pro.await();//生产者线程陷入冻结//这个句式会抛出一个InterruptedException异常sp++;System.out.println("生产者"+Thread.currentThread().getName()+"----"+sp);f=false;con.signal();//仅仅唤醒消费者线程}finally{lock.unlock();//释放锁}/*这里是所以要使用try...finally句型是因为确保一定要执行 lock.unlock();也是因为前面的pro.await();会向外抛出一个异常,如果没有这个句型程序就会跳出去而没有执行lock.unlock();这样的话线程就没有释放锁*/}public  void  xiaofei() throws InterruptedException{lock.lock();try{while(f==true)con.await();//消费者线程陷入冻结System.out.println("消费者"+Thread.currentThread().getName()+"----"+sp);f=true;pro.signal();//唤醒生产者线程}finally{lock.unlock();}}}class   Shengchangzhe  implements  Runnable{private  Shipin   a ;Shengchangzhe(Shipin   a){this.a=a;}public  void  run(){while(true){try{a.shengchang();}catch(Exception e){}}}}class  Xiaofeizhe  implements  Runnable{private  Shipin   a ;Xiaofeizhe(Shipin   a){this.a=a;}public  void  run(){while(true){try{a.xiaofei();}catch(Exception e){}}}}
/*对前面的例子做了一个改进:有生产者,检查者,消费者先要由生产者生产食品,然后由检查者检测食品,最后由消费者消化食品。*/
import java.util.concurrent.locks.*;class  Xctx7{public  static  void  main(String[] args){Shipin  a=new Shipin();Shengchangzhe  b1=new Shengchangzhe(a);Xiaofeizhe     b2=new Xiaofeizhe(a);Jiancezhe      b3=new Jiancezhe(a);Thread  t1=new Thread(b1);Thread  t2=new Thread(b1);Thread t3=new Thread(b2);Thread  t4=new Thread(b2);Thread t5=new Thread(b3);Thread  t6=new Thread(b3);t1.start();t2.start();t3.start();t4.start();t5.start();t6.start();System.out.println("HelloWorld!");}}class   Shipin{private  int sp=0;private  int  f=1;private  Lock lock=new ReentrantLock();//将锁作为一个对象了private  Condition  pro= lock.newCondition();private  Condition  con= lock.newCondition();private  Condition  jc = lock.newCondition();public    void shengchang() throws InterruptedException{lock.lock();try{while(f!=1){pro.await();//生产者线程陷入冻结}sp++;System.out.println("生产者"+Thread.currentThread().getName()+"----"+sp);f=2;jc.signal();//唤醒检测者线程}finally{lock.unlock();//释放锁}}public  void  xiaofei() throws   InterruptedException{lock.lock();try{while(f!=3){con.await();//消费者线程陷入冻结}System.out.println("消费者"+Thread.currentThread().getName()+"----------"+sp);f=1;pro.signal();//唤醒生产者线程}finally{lock.unlock();}}public  void  jiance() throws  InterruptedException  //检测方法{lock.lock();try{while(f!=2){jc.await();//检测者线程陷入冻结}System.out.println("检测者"+Thread.currentThread().getName()+"-------"+sp);f=3;con.signal();//唤醒消费者线程}finally{lock.unlock();}}}class   Shengchangzhe  implements  Runnable{privateShipin   a ;Shengchangzhe(Shipin   a){this.a=a;}public   void   run(){while(true){try{a.shengchang();}catch(Exception e){}}}}class   Xiaofeizhe  implements   Runnable{private   Shipin   a ;Xiaofeizhe(Shipin   a){this.a=a;}public  void  run(){while(true){try{a.xiaofei();}catch(Exception e){}}}}class   Jiancezhe  implements Runnable{private   Shipin   a ;Jiancezhe(Shipin   a){this.a=a;}public   void   run(){while(true){try{a.jiance();}catch(Exception e){}}}}/*以上的代码编译运行结果如下:生产者Thread-0----1Hello World!检测者Thread-4-------1消费者Thread-3----------1生产者Thread-0----2检测者Thread-5-------2消费者Thread-3----------2生产者Thread-1----3检测者Thread-5-------3消费者Thread-2----------3生产者Thread-0----4检测者Thread-4-------4消费者Thread-3----------4生产者Thread-1----5检测者Thread-5-------5消费者Thread-2----------5生产者Thread-0----6检测者Thread-4-------6消费者Thread-3----------6生产者Thread-1----7检测者Thread-5-------7消费者Thread-2----------7生产者Thread-0----8检测者Thread-4-------8消费者Thread-3----------8生产者Thread-1----9检测者Thread-5-------9消费者Thread-2----------9生产者Thread-0----10检测者Thread-4-------10消费者Thread-3----------10生产者Thread-1----11检测者Thread-5-------11消费者Thread-2----------11生产者Thread-0----12检测者Thread-4-------12消费者Thread-3----------12生产者Thread-1----13检测者Thread-5-------13消费者Thread-2----------13生产者Thread-0----14检测者Thread-4-------14消费者Thread-3----------14生产者Thread-1----15检测者Thread-5-------15消费者Thread-2----------15生产者Thread-0----16检测者Thread-4-------16消费者Thread-3----------16生产者Thread-1----17检测者Thread-5-------17消费者Thread-2----------17生产者Thread-0----18检测者Thread-4-------18消费者Thread-3----------18生产者Thread-1----19检测者Thread-5-------19消费者Thread-2----------19生产者Thread-0----20检测者Thread-4-------20消费者Thread-3----------20生产者Thread-1----21检测者Thread-5-------21消费者Thread-2----------21生产者Thread-0----22检测者Thread-4-------22消费者Thread-3----------22生产者Thread-1----23检测者Thread-5-------23消费者Thread-2----------23生产者Thread-0----24检测者Thread-4-------24消费者Thread-3----------24生产者Thread-1----25检测者Thread-5-------25消费者Thread-2----------25生产者Thread-0----26检测者Thread-4-------26消费者Thread-3----------26生产者Thread-1----27检测者Thread-5-------27消费者Thread-2----------27生产者Thread-0----28检测者Thread-4-------28消费者Thread-3----------28生产者Thread-1----29检测者Thread-5-------29消费者Thread-2----------29生产者Thread-0----30检测者Thread-4-------30消费者Thread-3----------30生产者Thread-1----31检测者Thread-5-------31消费者Thread-2----------31生产者Thread-0----32检测者Thread-4-------32消费者Thread-3----------32生产者Thread-1----33检测者Thread-5-------33消费者Thread-2----------33生产者Thread-0----34检测者Thread-4-------34消费者Thread-3----------34生产者Thread-1----35检测者Thread-5-------35消费者Thread-2----------35生产者Thread-0----36检测者Thread-4-------36消费者Thread-3----------36生产者Thread-1----37检测者Thread-5-------37消费者Thread-2----------37生产者Thread-0----38检测者Thread-4-------38消费者Thread-3----------38生产者Thread-1----39检测者Thread-5-------39消费者Thread-2----------39生产者Thread-0----40检测者Thread-4-------40消费者Thread-3----------40生产者Thread-1----41检测者Thread-5-------41消费者Thread-2----------41生产者Thread-0----42检测者Thread-4-------42消费者Thread-3----------42生产者Thread-1----43检测者Thread-5-------43消费者Thread-2----------43生产者Thread-0----44检测者Thread-4-------44消费者Thread-3----------44生产者Thread-1----45检测者Thread-5-------45消费者Thread-2----------45生产者Thread-0----46检测者Thread-4-------46消费者Thread-3----------46生产者Thread-1----47检测者Thread-5-------47消费者Thread-2----------47生产者Thread-0----48检测者Thread-4-------48消费者Thread-3----------48生产者Thread-1----49检测者Thread-5-------49消费者Thread-2----------49生产者Thread-0----50检测者Thread-4-------50消费者Thread-3----------50生产者Thread-1----51检测者Thread-5-------51消费者Thread-2----------51生产者Thread-0----52检测者Thread-4-------52消费者Thread-3----------52生产者Thread-1----53检测者Thread-5-------53消费者Thread-2----------53生产者Thread-0----54检测者Thread-4-------54消费者Thread-3----------54生产者Thread-1----55检测者Thread-5-------55消费者Thread-2----------55生产者Thread-0----56检测者Thread-4-------56消费者Thread-3----------56生产者Thread-1----57检测者Thread-5-------57消费者Thread-2----------57生产者Thread-0----58检测者Thread-4-------58消费者Thread-3----------58生产者Thread-1----59检测者Thread-5-------59消费者Thread-2----------59生产者Thread-0----60检测者Thread-4-------60消费者Thread-3----------60生产者Thread-1----61检测者Thread-5-------61消费者Thread-2----------61生产者Thread-0----62检测者Thread-4-------62消费者Thread-3----------62生产者Thread-1----63检测者Thread-5-------63消费者Thread-2----------63*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: