关于练习线程的感想。

 

  我看了下别的大神的博客。结合自己的练习了下多线程的并发问题。我觉得就多线程而言。最重要的就是要把整个业务放进同步锁里面。

synchronized这个关键字有两种用法1、放方法名前形成同步方法;2、放在块前构成同步块。


比如:

class thread4Test implements Runnable{
    private int ticket=10;
    public synchronized void run()
    {
        for(int i=1;i<50;i++)
        {
            if(ticket>0)
            {
                //休眠1s秒中,为了使效果更明显,否则可能出不了效果
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"号窗口卖出"+this.ticket--+"号票");
            }
        }
    }
}

输出结果是

a号窗口卖出10号票
a号窗口卖出9号票
a号窗口卖出8号票
a号窗口卖出7号票
a号窗口卖出6号票
a号窗口卖出5号票
a号窗口卖出4号票
a号窗口卖出3号票
a号窗口卖出2号票
a号窗口卖出1号票

 

这里的同步锁的位置是在run方法里面。同步的是run方法。这样的话启动一条线程之后就会一直运行。直到a执行完毕之后b再去执行的时候就没有票了。

例如:

class thread5Test implements Runnable{
  private int ticket=10;
  public void run()
  {
      for(int i=1;i<50;i++)
      {
         
          if(ticket>0)
          {
              synchronized(this){
              //休眠1s秒中,为了使效果更明显,否则可能出不了效果
              try {
                  Thread.sleep(1000);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
              System.out.println(Thread.currentThread().getName()+"号窗口卖出"+this.ticket--+"号票");
              }
          }
      }
  }
}

执行结果:

a号窗口卖出10号票
c号窗口卖出9号票
b号窗口卖出8号票
b号窗口卖出7号票
b号窗口卖出6号票
b号窗口卖出5号票
c号窗口卖出4号票
a号窗口卖出3号票
a号窗口卖出2号票
a号窗口卖出1号票
c号窗口卖出0号票
b号窗口卖出-1号票

synchronized放错了位置,程序将synchronized放在了if语句的后面,当b线程取出2好票以后,此时ticket=1,等下一次a、b、c线程来的时候,ticket=1>0就进入if语句体,这时cpu分给线程的时间片是先b在c后a这样就导致了上面的结果。

例如:

class thread6Test implements Runnable{
private int ticket=10;
public void run()
{
    synchronized(this){
    for(int i=1;i<50;i++)
    {
        if(ticket>0)
        {
            
            //休眠1s秒中,为了使效果更明显,否则可能出不了效果
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"号窗口卖出"+this.ticket--+"号票");
            }
        }
    }
}

输出结果:

这里的执行结果也是只有a售票。因为同步锁的时候同步了整个的循环。
整个程序的业务是什么?业务就是售票。换句话说。就是说要售票的时候不能出错。售票的时候各个窗口还有业务彼此不能相互交叉干扰。
当一个线程要使用火车票这个资源时,我们就交给它一把锁,等它把事情做完后在把锁给另一个要用这个资源的线程

那么。同步的时候就不是同步程序了。应该是同步销售火车票的这个业务。例如:

class thread3Test implements Runnable{
    private int ticket=10;
    public void run(){
        for(int i=1;i<50;i++){
            if(ticket>0){
                try {
                    Thread.sleep(1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                this.sale();
            }
        }
    }
    public synchronized void sale(){
        if(ticket>0){System.out.println(Thread.currentThread().getName()+"号窗口卖出第"+this.ticket--+"张票!");}
    }
}

这里销售火车票就是业务。在这里同步的时候同步业务,而不是同步后台的票的处理的程序。票就算是再处理出来的也是票。
处理的时候是处理的业务。也就是售票。那么,只要售票的时候不会出现问题就好。同步应该放在业务上,而不是票的处理上。

我是小菜鸟。这也是我第一次写博客。希望大家能够不吝啬的多多的指教。同时,也感谢各位大师。大神们在博客园的分享。让我学到了很多东西。
在此,我也把我的一点小小的经验分享出来。希望更多的人能够参与到其中来。
我也说了。我也是一直小菜鸟。希望大家能够给我多多的指教。我只是写出来了一点我自己的看法还有经验。
编程这个东西是一个务实,严谨的工作。只有经得起考验的程序才是好的程序。
在此。也希望大家能够给我多多的指教。提供更多的看法。我也会虚心的采纳。不断的学习。不断的成长。

 

 

posted @ 2013-04-17 17:42  only.lonely  阅读(203)  评论(0编辑  收藏  举报