Java-多线程总结

 1.调用run和调用start有什么区别

   run方法只是类里的一个普通方法,调用该方法只是执行该方法里的代码,程序中还是只有主线程这一线程

   而start方法是将该线程变成可运行状态(还没运行),等待cpu切换来时就可以启动执行该线程下的run方法。

   即start方法可以启动线程,而run方法只是Thread的一个普通方法。

2.静态的同步方法与其他同步代码块之间的同步

   静态同步方法:public static synchronized void method(){...};

                      //它的同步锁是该方法所属字节码文件对象即 类名.getClass()或 类名.class

   所以与它同步的代码块里必须是:synchronized(类名.class) {.....}

   非静态的方法的同步锁是this对象本身

3.总结

  • 同步的好处:解决了线程的安全问题。
  • 同步的弊端:相对降低了效率,因为同步外的线程的都会判断同步锁。
  • 同步的前提:同步中必须有多个线程并使用同一个锁

4.wait 和 sleep 区别?

  1. wait可以指定时间也可以不指定。sleep必须指定时间。
  2. 在同步中时,对cpu的执行权和锁的处理不同。  wait:释放执行权,释放锁。  sleep:释放执行权,不释放锁。

5.wait,notify,notifyAll方法使用

   这三个方法经常用在线程间的通信,比如:X线程对某个数据进行一次更改后,Y线程对其读取一次,是一次更改一次读取交替进行,

   不是更改多次后再读取多次。它们只能在同步方法或同步代码块中调用,且同步锁必须为这三个方法的共同对象。无论线程调用一个

   对象的wait还是notify方法,该线程必须先得到该对象的锁,才可以调用该方法。notify只能唤醒同一个对象监视器中调用wait的线程。

   以下是,生产者生产(更改)一次后,换消费者消费(读取)一次。依次交替。

 

package hq.Thread.Test;

public class Test {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
         Q q=new Q ();
         Consumer c=new Consumer(q);
         Producer p=new Producer (q);
         new Thread (c).start();
         new Thread (p).start();
         
    }

}
//消费者线程(读取)
class Consumer implements Runnable
{
    private Q q=null;
    public Consumer (Q q)
    {
        this.q=q;
    }
    public void run ()
    {
         while(true)
         {
             //System.out.println(Thread.currentThread().getName());
            try {
                q.get();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
         }
    }

}
//生产者线程(更改)
class Producer implements Runnable
{
    private Q q=null;
    private int num=1;
    public Producer (Q q)
    {
      this.q=q;
     }
     public void run ()
     {
         while(true)
         {
         
             //System.out.println(Thread.currentThread().getName());
             if(num==1)
             {
                try {
                    q.put("陈奕迅","男");
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
             }
             else if(num==0)
             {
                 try {
                    q.put("王菲","女");
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
             }
         
        num=(num+1)%2;
         }
     }
}
//共同操作的数据Q,由线程对其进行修改,读取,
//因为要修改和读取同步(即两个方法的同步锁为Q对象),且数据在Q内部,所以应具有操作数据的方法
class Q
{
    private String name;
    private String sex;
  private boolean flag=true;//以标志位来控制更改或读取操作。
    //更改的同步方法
    public synchronized void put(String name,String sex) throws InterruptedException
    {
        //默认标志位为true时更改否则等待
        if(!isFlag())
            wait();
      this.name=name;
        this.sex=sex;
       //更改完后换读取,且唤醒读取(为false标志)的线程
        this.flag=false;
        notify();
         System.out.println(Thread.currentThread().getName());
         
    }
  //读取的同步方法
  public synchronized void get() throws InterruptedException
    {
        //默认标志位为flase时读取否则等待
        if(isFlag())
            wait();
        System.out.println(this.name+":"+this.sex);
        //读取完后换更改,且唤醒更改(为true)的线程
        this.flag=true;
        notify();
         System.out.println(Thread.currentThread().getName());
         
    }

    public boolean isFlag()
    {
           return flag;
    }
    public void setFlag(boolean flag)
    {
           this.flag=flag;
    }
    public String getName()
  {
        return name;
    }
    public void setName(String name)
    {
        this.name=name;
    }
  public String getSex()
  {
        return sex;
    }
    public void getSex(String sex)
    {
        this.sex=sex;
    }

}

 

posted @ 2015-01-19 16:27  beyondbycyx  阅读(155)  评论(0编辑  收藏  举报