A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

主题:多线程
1线程间通讯
其实是多个线程在操作同一个资源,但是操作的动作不同
1.是不是两个或两个以上的线程。解决办法 两个线程都要被同步
2.是不是同一个锁。 解决办法 找同一个对象作为锁。
2等待唤醒机制
wait()后,线程就会存在线程池中,notify()后就会将线程池中的线程唤醒
notifyAll():唤醒线程池中所有的线程
例一:

  1. /对InputOutput的优化,双线程输出Mikeman和韩梅梅女
  2. class Rec
  3. {
  4.         private String name;//优化1.私有化
  5.         private String sex;
  6.         private boolean flag=false;
  7.         public synchronized void set(String name,String sex)//优化2构建对外访问,同步函数
  8.         {
  9.                 if (this.flag)//如果真运行wait(),一开始为false,不运行,运行一次后变为true,
  10.                         try{this.wait();}catch(Exception e){}//wait()和后面的notify()必须是同步锁的r,标识锁
  11.                 this.name=name;
  12.                 this.sex=sex;
  13.                 this.flag=true;
  14.                 this.notify();
  15.         }
  16.         public synchronized void out()//优化2构建对外访问,同步函数
  17.         {
  18.                 if (!this.flag)//如果真运行wait(),一开始flag为true,所以是!flag,第一次不运行,运行一次后flag变为false
  19.                                 try{this.wait();}catch(Exception e){}
  20.                 System.out.println(name+sex);
  21.                 this.flag=false;
  22.                 this.notify();
  23.         }
  24. }

  25. class Input implements Runnable
  26. {
  27.         private Rec r;
  28.         Input(Rec r)
  29.         {
  30.                 this.r=r;
  31.         }

  32.         public void run()
  33.         {
  34.                 int x=0;
  35.                 while (true)
  36.                 {
  37.                                 if (x==0)
  38.                                         r.set("Mike","man");
  39.                                 else
  40.                                         r.set("韩梅梅","女");
  41.                                 x=(x+1)%2;
  42.                 }       
  43.         }
  44. }

  45. class Output implements Runnable
  46. {
  47.         private Rec r;
  48.         Output(Rec r)
  49.         {
  50.                 this.r=r;
  51.         }
  52.         public void run()
  53.         {
  54.                 while(true)
  55.                 {
  56.                         r.out();
  57.                 }       
  58.         }
  59. }

  60. class  InputOutput
  61. {
  62.         public static void main(String[] args)
  63.         {
  64.                 Rec r =new Rec();

  65.                 new Thread(new Input(r)).start();//优化三,匿名函数,简化书写
  66.                 new Thread(new Output(r)).start();
  67.         }
  68. }
复制代码

wait(),notify(),notifyAll()
都使用在同步中,因为要对持有监视器(锁)的线程操作
所以要使用在同步中,因为只有同步才具有锁
为什么这些操作线程的方法要定义在Object类中?
因为这些方法在操作同步线程中线程时,都必须要标识它们所操作线程只有的锁
只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒
不可以对不同的锁中的线程进行唤醒
也就是说,等待和唤醒必须是同一个锁
而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object类中
例二:while (this.flag)//让唤醒的线程都重新判断标记

  1. while (this.flag)//让唤醒的线程都重新判断标记
  2.                         {
  3.                                 try
  4.                                 {this.wait();}
  5.                                 catch (Exception e){}
  6.                         }
  7.                 this.name=name+"--"+count++;

  8.                 System.out.println(Thread.currentThread().getName()+"--"+"生产者"+"--"+this.name);
  9.                 flag=true;
  10.                 this.notifyAll();//唤醒对方线程,避免死锁
复制代码

3  JDK1.5版升级版
JDK1.5中提供了多线程升级解决方案,显示的锁机制,和显示锁对象等待唤醒操作机制
将同步synchronized替换成了Lock操作
Object中的waitnotifynotifyAll,替换成了Condition对象
该对象可以Lock锁 进行获取。一个锁可以对应多个condition对象
Lock:替代了Synchronized
        lock
        unlock
        newCondition()
Condition:替代了Object wait notify notifyAll
        await();
        signal();
        signalAll();
注意:释放锁的动作一定要执行(finally{}
例三:

  1. class Res{
  2.         private String name;
  3.         private int count=1;
  4.         private boolean flag =false;//资源空间的标记

  5.         private Lock lock=new ReentrantLock()

  6.         private Condition condition_pro=lock.newCondition();
  7.         private Condition condition_con=lock.newCondition();//一个锁可以对应多个Condition对象
  8.         public  void set(String name){
  9.                 lock.lock();//代替synchronized
  10.                 try{
  11.                         while (this.flag)
  12.                                 condition_pro.await();//代替wait()

  13.                         this.name=name+"--"+count++;

  14.                         System.out.println(Thread.currentThread().getName()+"--"+"生产者"+"--"+this.name);
  15.                         flag=true;
  16.                         condition_con.signal();//代替notifyAll()
  17.                 }
  18.                 finally {
  19.                         lock.unlock();
  20.                 }

  21.         }
  22.         public  void get(){
  23.                 lock.lock();
  24.                 try{
  25.                         while(!flag)
  26.                                 condition_con.await();

  27.                         System.out.println(Thread.currentThread().getName()+"--"+"消费者"+"------"+this.name);
  28.                         flag=false;
  29.                         condition_pro.signal();
  30.                 }
  31.                
  32.                 finally {
  33.                         lock.unlock();
  34.                 }
  35.                
  36.         }
  37. }
复制代码


4 停止线程
run方法结束,就会停止线程。开启多线程运行,运行代码通常是循环结构,只要控制住循环就可以让线程结束。方法:改变标记使循环结束
特殊情况:
当线程处于了冻结状态,就不会取到标记,那么线程就不会结束。
当没有指定的方式让冻结的线程恢复到运行状态时,这是需要对冻结进行清除。强制让线程恢复到运行状态中来,这样就可以操作标记让线程结束。
Thread类中提供了该方法   线程.interrupt();  中断异常(此时会发生异常)
5 守护线程、join方法、优先级
守护线程:(后台线程)
setDaemon将线程标记为守护线程或者用户线程。
setDaemon在启动线程前调用。当现存线程都是守护线程后,jvm退出
例:t1.setDaemontrue);
Join方法
join():抢夺cpu执行权
A线程执行到了B线程join方法时,A就会等待,等B线程执行完,A才会执行。Join可以用来临时加入线程执行。
例:t1.join();
优先级:
setPriority1-10)设置优先级
有三个标准:Thread.MAX_PRIORITY(10)
Thread.MIN_PRIORITY(1)
Thread.NORM_PRIORITY(5)
优先级越高,抢夺cpu执行权的几率越高
例:t1.setPriority(Thread.MAX_PRIORITY);
yield:暂停当前正在执行的线程对象,并执行其他线程
例:Thread.yield();

2 个回复

倒序浏览
看得懂的直接跳过,看不懂的还是看不懂
回复 使用道具 举报
继续努力!!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马