JAVA 11(多线程)

线程间通信,其实就是多个线程在操作同一个资源,但操作动作不同。
 
 
同步代码块用了同一个锁。
 
public class Test
{
 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();
 }
}
 
class Res
{
 String name;
 String sex;
}
 
class Input implements Runnable
{
 Res r ;
 
 Input(Res r)
 {
  this.r = r;
 }
 public void run()
 {
  boolean b = true;
  while(true)
  {
   synchronized(r)
   {
   if(b)
   {
    r.name="mike";
    r.sex="man";
    b=false;
   }
   else
   {
    r.name="丽丽";
    r.sex="女女女女";
    b=true;
   }
   }
  }
 }
}
 
class Output implements Runnable
{
 Res r;
 Output(Res r)
 {
  this.r=r;
 }
 public void run()
 {
  while(true)
  {
   synchronized(r)
   {
   System.out.println(r.name+"....."+r.sex);
   }
  }
 }
}
 
改代码 会打印重复的 同一个人,利用线程直接的通信修改,在Res中给一个标记。
 
等待唤醒机制
 
 
非静态同步函数用的锁时this。
静态同步函数用的锁时 类名.class。
同步代码块用的锁任意。自己设置的
 
 
wait()   :格式 try{} catch() {}
notify() 
notifyAll()
 
三个方法都继承于Object类,后两个方法必须有对象的监视器才可以使用(也就是同步中的锁,必须在同步中才可以使用)
 
都使用在同步中,因为要对持有监视器(锁)的线程操作,所以要使用在同步中,因为只有在同步中,才有锁。
 
为什么操作线程的方法要定义在Object中呢,因为这些方法在操作同步中的线程时,都必须要标示他们所操作线程持有的锁,只有同一个锁上的被等待线程可以被同一个锁上notify()唤醒,不可以对不同所中的线程进行唤醒
也就是说,等待和唤醒必须是同一个锁,而锁可以是任意对象,所以可以被任意对象调用的方法定义在Obj类中。
 
 
public class Test
{
 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();
 }
}
 
class Res
{
 String name;
 String sex;
 boolean flag = false;
}
 
class Input implements Runnable
{
 Res r ;
 
 Input(Res r)
 {
  this.r = r;
 }
 public void run()
 {
  boolean b = true;
  while(true)
  {
   synchronized(r)
   {
    if(r.flag)
     try
    {
     r.wait();
    }
   catch(Exception e)
   {
   
   }
   if(b)
   {
    r.name="mike";
    r.sex="man";
    b=false;
   }
   else
   {
    r.name="丽丽";
    r.sex="女女女女";
    b=true;
   }
   r.flag=true;
   r.notify();
   }
  }
 }
}
 
class Output implements Runnable
{
 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();
   }
  }
 }
}
 
 
继续举例:
多个线程负责生产,多个线程负责消费。注意notifyAll 和while(flag)
 
对于多个生产者和消费者。
为什么要定义while判断标记?
让被唤醒的线程再一次判断标记。
 
为什么要定义notifyAll
因为需要唤醒对方线程。
因为只用notify的话,容易出只唤醒本方线程的情况,导致程序中所有线程都等待。
 
 
 
public class Test
{
 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(con);
  Thread t3 = new Thread(pro);
  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;
 
 public synchronized void set(String name)
 {
  while(flag)
   try
  {
    wait();
  }
  catch(Exception e)
  {
   
  }
  this.name = name+"--"+count++;
  System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name); 
  flag = true;
  this.notifyAll();
 }
 public synchronized void out()
 {
  while(!flag)
   try
  {
    wait();
  }
  catch(Exception e)
  {
   
  }
  System.out.println(Thread.currentThread().getName()+"...消费者......."+this.name);
  flag = false;
  this.notifyAll();
 }
 
}
 
class Producer implements Runnable
{
 private Resource res;
 public void run()
 {
  while(true)
  {
   res.set("+商品+");
  }
 }
 Producer(Resource res)
 {
  this.res=res;
 }
}
 
class Consumer implements Runnable
{
 private Resource res;
 public void run()
 {
  while(true)
  {
   res.out();
  }
 }
 Consumer(Resource res)
 {
  this.res=res;
 }
 
}
 
 
jdk5升级之后
 
java.util.concurrent.locks 接口
 
jdk1.5中提供了多线程的升级解决方案,将同步的Synchronized 替换成Lock操作,将Object中的wait,notify,nofityAll替换成立Condition对象,该对象可以Lock锁,进行获取。一个锁可以对应多个Condition。
 
JDK1.5 中提供了多线程升级解决方案。
将同步Synchronized替换成现实Lock操作。
将Object中的wait,notify notifyAll,替换了Condition对象。
该对象可以Lock锁 进行获取。
该示例中,实现了本方只唤醒对方操作。
 
Lock:替代了Synchronized
 lock
 unlock
 new Condition()
 
Condition:替代了Object wait notify notifyAll
 await();
 signal();
 signalAll();
 
 
在该实力中,实现了本方只唤醒对方的操作。
更改之后的代码:
 
import java.util.concurrent.locks.*;
 
class Test
{
 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();
 
 }
}
 
/*
JDK1.5 中提供了多线程升级解决方案。
将同步Synchronized替换成现实Lock操作。
将Object中的wait,notify notifyAll,替换了Condition对象。
该对象可以Lock锁 进行获取。
该示例中,实现了本方只唤醒对方操作。
 
Lock:替代了Synchronized
 lock
 unlock
 newCondition()
 
Condition:替代了Object wait notify notifyAll
 await();
 signal();
 signalAll();
*/
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)
   {
   }
  }
 }
}
 
 
 
 
停止线程
 
停止线程的原理
只有一种方法,就是run()方法结束
 
线程.interrupt  //强制唤醒
 
stop方法已经过时。
 
如何停止线程?
只有一种,run方法结束。
开启多线程运行,运行代码通常是循环结构。
 
只要控制住循环,就可以让run方法结束,也就是线程结束。
 
 
特殊情况:
当线程处于了冻结状态。
就不会读取到标记。那么线程就不会结束。
 
当没有指定的方式让冻结的线程恢复到运行状态是,这时需要对冻结进行清除。
强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。
 
Thread类提供该方法 interrupt();
 
 
 
 
设置为守护线程,当其他线程都结束后,并且只剩下守护线程,守护线程自动结束
而且必须早start()之前设置守护线程
 
 
join方法
 
t1.join(); 抢夺cpu执行权,当t1执行结束的时候,主线程才解冻。
 
join:
当A线程执行到了B线程的.join()方法时,A就会等待。等B线程都执行完,A才会执行。
 
join可以用来临时加入线程执行。
 
 
 
线程的优先级
 
 
 
 
 
 
自己写的代码:
import java.util.concurrent.locks.*;
import java.util.concurrent.locks.Lock.*;
 
public class Test
{
 public static void main(String args[])
 {
  Resource r = new Resource();
  Pro p = new Pro(r);
  Cro c = new Cro(r);
  Thread t1 = new Thread(p);
  Thread t2 = new Thread(p);
  Thread t3 = new Thread(c);
  Thread t4 = new Thread(c);
  t1.start();
  t2.start();
  t3.start();
  t4.start();
 
 
 }
}
 
class Resource
{
 
 private boolean flag = false;
 private int count = 1;
 
 private Lock lock = new ReentrantLock();
 private Condition con_pro = lock.newCondition();
 private Condition con_con = lock.newCondition();
 
 public void set()
 {
 
   lock.lock();
   
    try {
     while(flag)
     con_pro.await();
     count++;
     System.out.println(Thread.currentThread().getName()+"生产了第"+count+"张票");
     flag=true;
     con_con.signal();
    } catch (InterruptedException e) {
     
    }
    finally
    {
     lock.unlock();
    }
   
   
 }
 
 
 public void hua()
 {
 
   lock.lock();
   
    try {
     while(!flag)
     con_con.await();
     System.out.println(Thread.currentThread().getName()+"消费了第"+count+"张票***");
     flag=false;
     con_pro.signal();
    } catch (InterruptedException e) {
     
    }
    finally
    {
     lock.unlock();
    }
   
 }
 
 
}
 
class Pro implements Runnable
{
 Resource r;
 Pro(Resource r)
 {
  this.r=r;
 }
 
 public void run()
 {
  while(true)
   r.set();
 }
}
 
class Cro implements Runnable
{
 Resource r;
 Cro(Resource r)
 {
  this.r=r;
 }
 
 public void run()
 {
  while(true)
   r.hua();
 }
}
posted @ 2015-07-25 15:15  hitz&x  阅读(277)  评论(0编辑  收藏  举报