• 05-java学习笔记-多线程2


    1.线程间通信-示例

    线程间通讯:
    其实就是多个线程在操作同一个资源,
    但是操作的动作不同。
    class Res
    {
         String name;
         String sex;
         boolean flag = false;
    }

    class Input implements Runnable
    {
         private Res r ;
         Input(Res r)
         {
              this.r = r;
         }
         public void run()
         {
              int x = 0;
              while(true)
              {
                   synchronized(r)
                   {

                        if(r.flag)
                             try{r.wait();}catch(Exception e){}
                        if(x==0)
                        {
                             r.name="mike";
                             r.sex="man";
                        }
                        else
                        {
                             r.name="丽丽";
                             r.sex = "女女女女女";
                        }
                        x = (x+1)%2;
                        r.flag = true;
                        r.notify();
                   }
              }
         }
    }

    class Output implements Runnable
    {
         private Res r ;
        
         Output(Res r)
         {
              this.r = r;
         }
         public void run()
         {
              while(true)
              {
                   synchronized(r)
                   {
                        if(!r.flag)
                             try{r.wait();}catch(Exception e){}
                        System.out.println(r.name+"...."+r.sex);
                        r.flag = false;
                        r.notify();
                   }
              }
         }
    }


    class  InputOutputDemo
    {
         public static void main(String[] args)
         {
              Res r = new Res();

              Input in = new Input(r);
              Output out = new Output(r);

              Thread t1 = new Thread(in);
              Thread t2 = new Thread(out);

              t1.start();
              t2.start();
         }
    }

    2.线程间通信-等待唤醒机制

    class Res
    {
         private String name;
         private String sex;
         private boolean flag = false;

         public synchronized void set(String name,String sex)
         {
              if(flag)
                   try{this.wait();}catch(Exception e){}
              this.name = name;
             
              this.sex = sex;
              flag = true;
              this.notify();
         }
         public synchronized void out()
         {
              if(!flag)
                   try{this.wait();}catch(Exception e){}
              System.out.println(name+"........"+sex);
              flag = false;
              this.notify();
         }
    }

    class Input implements Runnable
    {
         private Res r ;
         Input(Res r)
         {
              this.r = r;
         }
         public void run()
         {
              int x = 0;
              while(true)
              {
                   if(x==0)                   
                        r.set("mike","man");                   
                   else    
                        r.set("丽丽","女女女女女");                   
                   x = (x+1)%2;
              }
         }
    }

    class Output implements Runnable
    {
         private Res r ;
        
         Output(Res r)
         {
              this.r = r;
         }
         public void run()
         {
              while(true)
              {
                   r.out();
              }
         }
    }

    class  InputOutputDemo2
    {
         public static void main(String[] args)
         {
              Res r = new Res();

              new Thread(new Input(r)).start();
              new Thread(new Output(r)).start();
              /*
              Input in = new Input(r);
              Output out = new Output(r);

              Thread t1 = new Thread(in);
              Thread t2 = new Thread(out);

              t1.start();
              t2.start();
              
    */
         }
    }
    wait();
    notify();
    notifyAll();
    这些方法都使用在同步中,因为要对持有监视器(锁)的线程操作。
    所以要使用在同步中,因为只有同步才具有锁。
    为什么这些操作线程的方法要定义Object类中呢?
    因为这些方法在操作同步中线程时,都必须要标识它们所操作线程只有的锁,
    只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒。
    不可以对不同锁中的线程进行唤醒。
    也就是说,等待和唤醒必须是同一个锁。
    而锁可以是任意对象,所以可以被任意对象调用的方法定义Object类中。

    3.线程间通信-生产者消费者
    class ProducerConsumerDemo
    {
         public static void main(String[] args)
         {
              Resource r = new Resource();

              Producer pro = new Producer(r);
              Consumer con = new Consumer(r);

              Thread t1 = new Thread(pro);
              Thread t2 = new Thread(pro);
              Thread t3 = new Thread(con);
              Thread t4 = new Thread(con);

              t1.start();
              t2.start();
              t3.start();
              t4.start();

         }
    }

    class Resource
    {
         private String name;
         private int count = 1;
         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();
         }
    }

    class Producer implements Runnable
    {
         private Resource res;

         Producer(Resource res)
         {
              this.res = res;
         }
         public void run()
         {
              while(true)
              {
                   res.set("+商品+");
              }
         }
    }

    class Consumer implements Runnable
    {
         private Resource res;

         Consumer(Resource res)
         {
              this.res = res;
         }
         public void run()
         {
              while(true)
              {
                   res.out();
              }
         }
    }
    对于多个生产者和消费者。
    为什么要定义while判断标记?
    原因:让被唤醒的线程再一次判断标记。
    为什么定义notifyAll?
    因为需要唤醒对方线程。
    因为只用notify,容易出现只唤醒本方线程的情况。导致程序中的所有线程都等待。
    4.线程间通信-生产者消费者JDK5.0升级版

    JDK1.5 中提供了多线程升级解决方案。
    import java.util.concurrent.locks.*;
    将同步Synchronized替换成现实Lock操作。
    将Object中的wait,notify notifyAll,替换了Condition对象。
    该对象可以Lock锁 进行获取。
    该示例中,实现了本方只唤醒对方操作。

    Lock:替代了Synchronized
         lock
         unlock
         newCondition()

    Condition:替代了Object wait notify notifyAll
         await();
         signal();
         signalAll();
    import java.util.concurrent.locks.*;

    class ProducerConsumerDemo2
    {
         public static void main(String[] args)
         {
              Resource r = new Resource();

              Producer pro = new Producer(r);
              Consumer con = new Consumer(r);

              Thread t1 = new Thread(pro);
              Thread t2 = new Thread(pro);
              Thread t3 = new Thread(con);
              Thread t4 = new Thread(con);

              t1.start();
              t2.start();
              t3.start();
              t4.start();

         }
    }


    class Resource
    {
         private String name;
         private int count = 1;
         private boolean flag = false;
                   //  t1    t2
         private Lock lock = new ReentrantLock();

         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();//释放锁的动作一定要执行。
              }
         }

         //  t3   t4 
         public  void out()throws InterruptedException
         {
              lock.lock();
              try
              {
                   while(!flag)
                        condition_con.await();
                   System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
                   flag = false;
                   condition_pro.signal();
              }
              finally
              {
                   lock.unlock();
              }
             
         }
    }

    class Producer implements Runnable
    {
         private Resource res;

         Producer(Resource res)
         {
              this.res = res;
         }
         public void run()
         {
              while(true)
              {
                   try
                   {
                        res.set("+商品+");
                   }
                   catch (InterruptedException e)
                   {
                   }
              }
         }
    }

    class Consumer implements Runnable
    {
         private Resource res;

         Consumer(Resource res)
         {
              this.res = res;
         }
         public void run()
         {
              while(true)
              {
                   try
                   {
                        res.out();
                   }
                   catch (InterruptedException e)
                   {
                   }
              }
         }
    }
    5.停止线程和守护线程
    stop方法已经过时。
    如何停止线程?
    只有一种,run方法结束。
    开启多线程运行,运行代码通常是循环结构。

    只要控制住循环,就可以让run方法结束,也就是线程结束。
    特殊情况:
    当线程处于了冻结状态。
    就不会读取到标记。那么线程就不会结束。

    当没有指定的方式让冻结的线程恢复到运行状态是,这时需要对冻结进行清除。
    强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。

    Thread类提供该方法 interrupt();
    setDaemon(true);
    将该线程标记为守护线程
    当正在运行的线程都是守护线程时,JVM退出。(后台线程)
    class StopThread implements Runnable
    {
         private boolean flag =true;
         public  void run()
         {
              while(flag)
              {
                  
                   System.out.println(Thread.currentThread().getName()+"....run");
              }
         }
         public void changeFlag()
         {
              flag = false;
         }
    }

    class  StopThreadDemo
    {
         public static void main(String[] args)
         {
              StopThread st = new StopThread();
             
              Thread t1 = new Thread(st);
              Thread t2 = new Thread(st);

              t1.setDaemon(true);
              t2.setDaemon(true);
              t1.start();
              t2.start();

              int num = 0;

              while(true)
              {
                   if(num++ == 60)
                   {
                        //st.changeFlag();
                        
    //t1.interrupt();
                        
    //t2.interrupt();
                        break;
                   }
                   System.out.println(Thread.currentThread().getName()+"......."+num);
              }
              System.out.println("over");
         }
    }
    7.Join方法 优先级&yield方法
    join:
    当A线程执行到了B线程的.join()方法时,A就会等待。等B线程都执行完,A才会执行。
    join可以用来临时加入线程执行。

    线程组ThreadGroup(不常用)
    优先级 
    代表抢资源的频率
    所有优先级包括主线程的默认优先级是5,一共是1—10.
    void setPriority(int newPriority)
    MAX_PRIORITY     10
    MIN_PRIORITY       1
    NORM_PRIORITY   5
    yield方法
    Thread.yield();//临时释放线程执行权
    class Demo implements Runnable
    {
         public void run()
         {
              for(int x=0; x<70; x++)
              {
                   System.out.println(Thread.currentThread().toString()+"....."+x);
                   Thread.yield();

              }
         }
    }

    class  JoinDemo
    {
         public static void main(String[] args) throws Exception
         {
              Demo d = new Demo();
              Thread t1 = new Thread(d);
              Thread t2 = new Thread(d);
              t1.start();
             
              //t1.setPriority(Thread.MAX_PRIORITY);

              t2.start();

              //t1.join();

              for(int x=0; x<80; x++)
              {
                   //System.out.println("main....."+x);
              }
              System.out.println("over");
         }
    }


  • 相关阅读:
    一种线程安全的handle
    基于数组的无锁队列(译)
    distri.lua的web运维工具
    distri.lua重写开源手游服务器框架Survive
    99 Lisp Problems 二叉树(P54~P69)
    99 Lisp Problems 列表处理(P1~P28)
    TSPL学习笔记(4):数组相关练习
    TSPL学习笔记(3):排序算法练习
    用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 热更新Live2D
    用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 使用FairyGUI (二)
  • 原文地址:https://www.cnblogs.com/chasingw/p/4849845.html
Copyright © 2020-2023  润新知