黑马程序员——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*/
相关文章推荐
- 黑马程序员--集合
- 黑马程序员----JAVA基础----多线程技术1
- Java程序员面试题
- 程序员脑子快更优秀吗?
- 加油吧实习生!职场菜鸟该如何理财
- 浅谈用力不用脑的程序员:你为什么蹉跎这么多年
- 为什么软件工程师应该养成写作的习惯?
- 算法-美团2015校招笔试:写一个复杂度为n的排序算法
- 黑马程序员——IO流缓冲区常见使用及自定义
- 黑马程序员--集合框架
- [黑马程序员](第51天)今晚复习小结
- 面试问题整理-02
- 黑马程序员—javaCollection集合框架
- 前端笔试面试题
- 面试总结之Java基础(未完工)
- 黑马程序员——Java面向对象封装继承多态
- 黑马程序员——高新技术---Java基础-多线程2
- 黑马程序员——高新技术---Java基础-多线程1
- 默齐致知电话面试
- 黑马程序员——Java学习总结:Java编程基础