Thread thread two multi-threaded service ticketing service

Ticket service

Introducing the problem:
There are one hundred tickets, divided into three slave windows

Test class

public static void main(String[] args) {
    RunnableImpl run=new RunnableImpl();
    Thread t0=new Thread(run);
    Thread t1=new Thread(run);
    Thread t2=new Thread(run);
    //调用start,开启多线程
    t0.start();
    t1.start();
    t2.start();
}

The first code:

Sold as long as there are tickets, three windows are three threads, and they are executed simultaneously

public class RunnableImpl implements Runnable {
private int ticket=100;
@Override
public void run() {
    while (true)
    {
        if(ticket>0)
        {
            System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票!");
            ticket--;
            
        }
    }

}
}

Effect:
Thread-2 is selling its 100th ticket!
Thread-2 is selling the 99th ticket!
Thread-2 is selling its 98th ticket!
Thread-1 is selling its 100th ticket!
Thread-1 is selling its 96th ticket!
Thread-2 is selling its 97th ticket!
Thread-2 is selling its 94th ticket!
Thread-2 is selling its 93rd ticket!
Thread-0 is selling its 100th ticket!
Reason: Threads compete for resources and enter the cpu at the same time. The system does not implement the rest, so there is a situation of repeated ticket sales.

improve algorithm:

The ticket selling time is changed to 10ms each, which means that the thread sleeps for 10ms. Makes resources buffered
static void sleep(long millis)
causes the currently executing thread to pause (temporarily stop execution) for a specified number of milliseconds, depending on the precision and accuracy of the system timer and scheduler.

public class RunnableImpl implements Runnable {
private int ticket=100;
@Override
public void run() {
    while (true)
    {
       try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if(ticket>0)
        {
            System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票!");
            ticket--;

        }
    }

}
}

Effect:
Thread-0 is selling the 100th ticket!
Thread-1 is selling its 100th ticket!
Thread-2 is selling its 100th ticket!
Thread-0 is selling its 97th ticket!
Thread-1 is selling its 97th ticket!
Thread-2 is selling its 95th ticket!
Reason: It was because of competing for cpu and entering at the same time. The improvement did not find the root cause!
Insert picture description here

Use synchronized (lock object) to synchronize code blocks

synchronized(lock object)
{code that may have thread safety issues (code that accesses shared data)}
Note:

  • 1. Through the lock object in the code block, any object can be used

  • 2. But it must be ensured that the lock object used by multiple threads is the same

  • 3. Lock object function:

  • Lock the synchronized code block, and only let one thread execute in the synchronized code block

      public class RunnableImpl implements Runnable {
      private  int ticket=100;
      //创建一个锁对象
    Object obj=new Object();
    @Override
     public void run() {
      while (true)
      {//同步代码块
          synchronized (obj)//也可以synchronized(this)
      {
    
          try {
              Thread.sleep(10);
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
          if(ticket>0)
          {
              System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票!");
              ticket--;
          }
      }
      }
       }
      }
    

    Effect:
    Thread-0 is selling the 100th ticket!
    Thread-0 is selling the 99th ticket!
    Thread-0 is selling its 98th ticket!
    Thread-0 is selling its 97th ticket!
    Thread-0 is selling its 96th ticket!
    Thread-0 is selling its 95th ticket!
    Thread-0 is selling its 94th ticket!
    Thread-0 is selling its 93rd ticket!
    principle:
    Insert picture description here

Use synchronization method

The lock object is this
step:
1. Extract the code that accessed the shared data and put it into a method
2. Add synchronized
code to the method :

public class RunnableImpl implements Runnable {
private int ticket=100;
//创建一个锁对象
@Override
public void run() {
    while (true)
    {//同步代码块
        payTicket();
    }

}
public synchronized void payTicket()
{
    if(ticket>0)
    {
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票!");
        ticket--;
    }
}
}

Effect:
Thread-0 is selling the 100th ticket!
Thread-0 is selling the 99th ticket!
Thread-0 is selling its 98th ticket!
Thread-0 is selling its 97th ticket!
Thread-0 is selling its 96th ticket!
Thread-0 is selling its 95th ticket!
Thread-0 is selling its 94th ticket!
Thread-0 is selling its 93rd ticket!
Set the ticket to private static, then the synchronization method is also a static method
. The
lock object of the static method is the class attribute of the class -> class file object (reflection
)
code:

public class RunnableImpl implements Runnable {
private static int ticket=100;

//创建一个锁对象
@Override
public void run() {
    while (true)
    {//同步代码块
        payTicket();
    }

}
/*使用静态方法解决同步问题*/
public static synchronized void payTicket()
{
    //去掉synchronized 关键字换上
    //synchronized(RunnableImpl.class){}
    if(ticket>0)
    {
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票!");
        ticket--;
    }
}
}

Guess you like

Origin blog.csdn.net/tangshuai96/article/details/102595126