------- android培训、java培训、期待与您交流! ---------
多线程(三)
多线程间的通信:将不同功能的代码封装在不同的线程代码中操作共同的资源。
实现的思想:
1.两线程实现Runnable接口,必须传入同一个对象
2.建立一资源类,设置成员变量,就是线程中的共享数据
3.在实现Runnable的子类中,将资源类名设置为成员变量,设置构造函数传入的参数为资源类型的变量,复写run()方法,操作资源数据。
等待唤醒机制:Wait()——notify(),判断条件为if
当线程中的通信操作同一功能的线程出现两个以上时,出现资源中的数据不匹配的情况,因此用等待唤醒机制,将资源数据中的输出统一。既输入线程中设置一组变量后就等待,并唤醒输出线程,输出数据完成后,将其等待并唤醒输入线程,这样设置会让数据匹配。但出现另外一种情况,就是某一时间段输入一组数据,但却输出两组数据。因为线程运行时,内存中会建立线程池,等待线程会存在线程池中,当唤醒时唤醒的是线程池中的线程,且Wait()、notify()需要标识锁,通常唤醒第一个被等待的,这样就会出现了的一种情况,t1、t2为输入线程,当t1线程等待后,t2线程先抢到CPU执行权,但因为标识为true,t2也等待;t3、t4为输出线程,当t3输出后,先唤醒t1,判断标识t3等待后,t1完成了输入,因为t2先等待,所以t2先被唤醒,导致输入两次,t2等待后,t3被唤醒输出一次,这样就导致了输入了两次,但只输出了一次。
private boolean flag = false;
// t1 t2
public synchronized void set(String name)
{
while(flag)
try{this.wait();}catch(Exception e){}//t1(放弃资格) t2(获取资格)
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
flag = true;
this.notifyAll();
}
// t3 t4
public synchronized void out()
{
while(!flag)
try{wait();}catch(Exception e){}//t3(放弃资格) t4(放弃资格)
System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
flag = false;
this.notifyAll();
}
}
解决方式一:
Wari()——notifyall(),判断条件为while
判断条件为while后,每次都要判断后才能wait,而notifyall可以将等待的输出线程全部唤醒。
解决方式二:1.5新特性Lok—unlock
Lock接口,ReentrantLock是Lock的实现类,有一些方法void | lock()获取锁,void | unlock释放锁;Condition | newCondition返回实例对象,该类中还有有void | await()等待方法,void | signal唤醒一个等待线程,这样可以用(对象. Signal)来唤醒指定线程。
private Condition condition_pro = lock.newCondition();
private Condition condition_con = lock.newCondition();
public void set(String name)throws InterruptedException
{
lock.lock();
try
{
while(flag)
condition_pro.await();//t1,t2
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
flag = true;
condition_con.signal();
}
finally
{
lock.unlock();//释放锁的动作一定要执行。
}
}
多线程中还有关于并发库也就是 Executors、ExecutorService线程池、调度器 ScheduledExecutorService的应用,后续在交通灯管理项目中会提到,这里就不赘述了。
总结:关于JAVA基础中的线程,当初学习毕老师的视频时个人觉得最难的还是生产消费模型和死锁,写这部分又不想把老师的所有的代码都写出来,太占篇幅,所以截取了部分代码,学习多线程个人觉得这些机制(同步、死锁、多线程间的通信等等)出现的原因弄清楚,多线程大概也就好理解了。再就是面对对象的理解,资源类怎么和线程类联系起来,各类之间的数据怎么联系起来,这几篇当中我根据自己的理解也介绍了下,个人觉得这对于我们这些初学者来说才是最关键的,便于我们理解代码和自己写代码。