您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > JavaSE_23_多线程(三)
源自清华值得信赖中国移动互联网研发培训专家1Threadtsynchronized(obj)obj.wait()obj.notify()线程t得到obj对象的锁线程t被放置在obj对象的等待池中,并自动释放obj对象的锁当某个线程执行了obj对象的notify方法后,会唤醒在此对象等待池中的某一个线程obj.notifyAll()当某个线程执行了obj对象的notifyAll方法后,会唤醒在此对象等待池中的所有线程源自清华值得信赖中国移动互联网研发培训专家线程等待:◦Object类中的wait()throwsInterruptedException方法,导致当前的线程等待,直到其他线程调用此对象的notify()方法或notifyAll()唤醒方法。线程唤醒:◦Object类中的notify()方法,唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的。◦Object类中的notifyAll()方法,唤醒在此对象监视器上等待的所有线程。这三个方法只能在被同步化(synchronized)的方法或代码块中调用见生产者消费者示例2源自清华值得信赖中国移动互联网研发培训专家生产者(Producer)与消费者(Consumer)的问题◦生产者将产品交给店员(Clerk),而消费者从店员处取走产品,店员一次只能持有固定数量的产品,如果生产者生产了过多的产品,店员叫生产者等一下,如果店中有空位放产品了再通知生产者继续生产;如果店中没有产品了,店员会告诉消费者等一下,如果店中有产品了再通知消费者来取走产品。TestProduct.java3源自清华值得信赖中国移动互联网研发培训专家场景类TestProduct//生产者消费者问题publicclassTestProduct{publicstaticvoidmain(String[]args){Clerkclerk=newClerk(0);//生产者线程ThreadproducerThread=newThread(newProducer(clerk));//消费者线程ThreadconsumerThread=newThread(newConsumer(clerk));producerThread.start();consumerThread.start();}}源自清华值得信赖中国移动互联网研发培训专家店员类Clerk(1)publicclassClerk{publicintproduct;//现存的商品数量0-20publicClerk(intproduct){this.product=product;}//从生产者处获取商品(进货)publicsynchronizedvoidaddProduct(){if(this.product=20){//货满,暂停进货System.out.println(货满,暂停进货);try{wait();}catch(InterruptedExceptione){e.printStackTrace();}//.....被唤醒后的后续代码}else{//可以进货this.product++;System.out.println(从生产者处获得了第+this.product+个商品);notify();//随机唤醒一个等待执行某个同步方法的对象}}.....待续源自清华值得信赖中国移动互联网研发培训专家店员类Clerk(2)//向消费者销售商品(卖货)publicsynchronizedvoidsellProduct(){if(this.product=0){System.out.println(售罄,估清,等待生产者提供商品);try{wait();}catch(InterruptedExceptione){e.printStackTrace();}//.....被唤醒后的后续代码}else{System.out.println(向消费者销售了第+(this.product)+个商品);this.product--;notify();//唤醒等待在this对象上的线程}}}源自清华值得信赖中国移动互联网研发培训专家消费者类ComsumerpublicclassConsumerimplementsRunnable{privateClerkclerk;publicConsumer(Clerkclerk){super();this.clerk=clerk;}publicvoidrun(){while(true){clerk.sellProduct();//调用一个Clerk类中的同步方法try{Thread.sleep((int)(Math.random()*2000));}catch(InterruptedExceptione){e.printStackTrace();}}}}源自清华值得信赖中国移动互联网研发培训专家生产者类ProducerpublicclassProducerimplementsRunnable{privateClerkclerk;publicProducer(Clerkclerk){super();this.clerk=clerk;}publicvoidrun(){while(true){clerk.addProduct();//调用一个Clerk类中的同步方法try{Thread.sleep((int)(Math.random()*1000));}catch(InterruptedExceptione){e.printStackTrace();}}}}源自清华值得信赖中国移动互联网研发培训专家练习Wife线程类,负责花钱1万的随机整数倍,每次不超过10万,如果余额不够但不为0,则有多少就花多少,没钱就wait;Husband线程类,负责赚钱,2万的随机整数倍,每次不超过10万;如果余额超过10万(含),则wait;如果余额加上新赚的钱超过10万,则保留(例如余额5万,新赚6万,则新余额11万)Account账户类(属性:intmoney,下限0万元)TestMoney场景类,启动一个Husband线程,启动两个Wife线程,模拟老公赚钱,老婆花钱的过程.源自清华值得信赖中国移动互联网研发培训专家方法说明start()新建的线程进入Runnable状态run()线程进入Running状态,程序员不要调用该方法,由系统调用wait()线程进入等待状态,等待被notify,这是一个对象方法,而不是线程方法notify()/notifyAll()唤醒其他的线程,这是一个对象方法,而不是线程方法staticvoidyield()暂停当前正在执行的线程对象,并执行其他线程。它是一个静态方法getPriority()/setPriority()获得/设置线程优先级1-1055interrupt()打断线程执行staticbooleaninterrupted()查看线程是否被打断staticvoidsleep()线程睡眠指定的一段时间join()调用这个方法的主线程,会等待加入的子线程完成isAlive()判断一个线程是否还是活动状态源自清华值得信赖中国移动互联网研发培训专家java.lang.ThreadLocal线程局部变量用于解决多个线程共享同一个对象时,对象属性的数据安全问题.每一个ThreadLocal对象就像一个整个楼的信箱,每一个线程只能打开其中的一个属于自己的信箱.这个信箱只能放一个对象.本质上ThreadLocal类中有一个Map,用于存储每一个线程的变量的副本.且无需知道key是什么(其实是当前线程).也不会错用到其他线程的局部变量.源自清华值得信赖中国移动互联网研发培训专家publicclassThreadLocalDemoimplementsRunnable{privatefinalstaticThreadLocalStudentstudentLocal=newThreadLocalStudent();publicstaticvoidmain(String[]agrs){ThreadLocalDemotd=newThreadLocalDemo();Threadt1=newThread(td,a);//td是共享数据,a是线程名Threadt2=newThread(td,b);t1.start();t2.start();}publicvoidrun(){this.accessStudent();//调用一个本类中自定义的方法}......源自清华值得信赖中国移动互联网研发培训专家publicStudentgetStudent(){//获取本地线程变量Studentstudent=studentLocal.get();//线程首次执行此方法的时候,studentLocal.get()肯定为nullif(student==null){//创建一个Student对象,并保存到本地线程变量studentLocal中student=newStudent();studentLocal.set(student);}returnstudent;}......源自清华值得信赖中国移动互联网研发培训专家publicvoidaccessStudent(){//获取当前线程的名字StringcurrentThreadName=Thread.currentThread().getName();//产生一个随机数并打印Randomrandom=newRandom();intage=random.nextInt(100);//获取一个Student对象,并将随机数年龄插入到对象属性中Studentstudent=this.getStudent();//调用自定义的方法student.setAge(age);//只能修改自己线程信箱中的对象System.out.println(thread+currentThreadName+firstreadageis:+student.getAge());try{Thread.sleep(500);}catch(InterruptedExceptionex){ex.printStackTrace();}System.out.println(thread+currentThreadName+secondreadageis:+student.getAge());}}源自清华值得信赖中国移动互联网研发培训专家[该同就得同]如果两个或两个以上的线程都修改同一对象(的属性),那么把执行修改的方法定义为被同步的,如果更新影响到了只读方法,那么该只读方法也要定义成同步的。[不该同就不同]不要滥用同步。多个线程如果访问的不是同一对象的同一属性,就不要将方法设置为synchronized的。[顺水推舟]每当一个方法释放某个对象的同步锁时,它应当调用notifyAll()来让等待队列中的其他线程有机会执行。源自清华值得信赖中国移动互联网研发培训专家[有借有还]仔细查看每次调用wait()方法,都有相应的notify()/notifyAll()方法,且它们均作用于同一个对象。[追根溯源]wait()和notify()/notifyAll()是Object类方法,而不是Thread类的方法。源自清华值得信赖中国移动互联网研发培训专家后台线程(守护线程)DaemonThread在后台运行的线程,为其他的线程提供服务可以用setDaemon(booleanb)来把一个线程设置成后台线程经常用于任务结束时的善后处理典型的后台线程是定时器Timer线程后台线程的优先级比其他线程的低如果没有“用户线程”在运行,JVM将退出,守护线程将被自动终止源自清华值得信赖中国移动互联网研发培训专家后台线程(守护线程)DaemonThreadpublicclassDaemonThreadextendsThread{publicvoidrun(){whi
本文标题:JavaSE_23_多线程(三)
链接地址:https://www.777doc.com/doc-2880414 .html