Home  >  Article  >  Java  >  Briefly describe multi-thread implementation and synchronous mutual exclusion communication

Briefly describe multi-thread implementation and synchronous mutual exclusion communication

Y2J
Y2JOriginal
2017-05-08 13:50:371090browse

The following editor will bring you a brief discussion on Java multi-threading implementation and synchronous mutual exclusion communication. The editor thinks it’s pretty good, so I’ll share it with you now and give it as a reference. Let’s follow the editor to take a look

In-depth understanding of Java multi-threadingThis article mainly understands and masters multi-threading from three aspects:

1 . The implementation of multi-threading, by inheriting the Thread class and implementing the Runnable interface, as well as the similarities and differences.

2. How to use synchronized in multi-thread synchronization and mutual exclusion.

3. How to use notify(), notifyAll(), and wait() in multi-threaded communication, as well as the code implementation of simple generators and consumers.

Let’s explain multi-threading in Java in detail:

1: Multi-threading implementation

Implementing multi-threading by inheriting the Threa class is mainly divided into the following three steps:

The first step: inherit Thread and implement the run() method in the Thread class.

Step 2: Define an instance of the Thread subclass.

Step 3: Start the thread by calling the start() method of the Thread class.

The following is a simple code implementation:

class myThread extends Thread{
  int n=100;
  public void run() {
    while (true) {
    if (n > 0) {
System.out.println(":"Thread.currentThread().getName()
              + "..." + n--);
        } else {
          break;
        }
      }
  }

}
public class ThreadTest {

  public static void main(String[] args) {
    myThread mythread=new myThread();
    mythread.setName("子线程");
    mythread.start();
  }

}

Several methods used in the above thread: Thread.currentThraed().getName() method gets the current thread's name. mythread.setName("child thread"); Rename the mythread thread to "child thread".

Implementing multi-threading by implementing the Runnable interface is mainly divided into the following steps:

The first step: implement run( in the Runnable interface )method. Generate an instance of Runnable.

Second step: Define a Thread class, and pass the above Runnable instance to the constructor method of the Thread class.

Step 3: Start the thread by calling the start() method of the Thread class.

The following is a simple code implementation:

class myRunnable implements Runnable{
  int n=100;
  public void run() {
    while (true) {
    if (n > 0) {
System.out.println(":"Thread.currentThread().getName()
              + "..." + n--);
        } else {
          break;
        }
      }
  }
}
public class ThreadTest {

  public static void main(String[] args) {
    myRunnable myrunnable = new myRunnable();
    Thread mythread=new Thread(myrunnable);
    mythread.setName("子线程");
    mythread.start();
  }
}

Since multi-threaded operation can be achieved by inheriting the Thread class and implementing the Runnable method, what are the two methods? What's the difference? Let’s take a look at the difference between the two through a ticket buying category:

Assume that there are a total of 100 tickets at the ticket office, and ticket sales are carried out through three windows. This means that we need to open three different Thread to realize ticket buying: First, let’s look at the way to realize ticket buying through Thread class:

class myThread extends Thread{
  int n=100;
  public void run() {
    while (true) {
    if (n > 0) {
System.out.println(":"Thread.currentThread().getName()
              + "..." + n--);
        } else {
          break;
        }
      }
  }
}
public class ThreadTest {
  public static void main(String[] args) {
    myThread m1=new myThread();
    myThread m2=new myThread();
    myThread m3=new myThread();
    m1.setName("窗口1");
    m2.setName("窗口2");
    m3.setName("窗口3");
    m1.start();
    m2.start();
    m3.start();
  }
}

The result is too long and I won’t show it. You can see that the three windows originally bought 100 tickets together, but As a result, each window bought 100 tickets. This is easy to understand because each window is an independent object, with its own n=100. Therefore, it is not feasible to implement the ticket buying function through the Thread class. In fact, the Thread method is used to implement multi-threading, in which the code executed by each thread is not the same piece of code.

Let’s take a look at how to implement the Runnable interface to implement the ticket buying function:

class myRunnable implements Runnable{
  int n=100;
  public void run() {
    while (true) {
    if (n > 0) {
System.out.println(":"Thread.currentThread().getName()
              + "..." + n--);
        } else {
          break;
        }
      }
  }
}
public class ThreadTest {
  public static void main(String[] args) {
    myRunnable myrunnable=new myRunnable();
    Thread m1=new Thread(myrunnable);
    Thread m2=new Thread(myrunnable);
    Thread m3=new Thread(myrunnable);
    m1.setName("窗口1");
    m2.setName("窗口2");
    m3.setName("窗口3");
    m1.start();
    m2.start();
    m3.start();
  }
}

It can be seen that the above three threads share the same subclass of Runnable , so just open three threads to execute the same runnable code. So there will be no situation of buying 300 tickets. But there are still problems with this program. We will improve this program after talking about the synchronization and mutual exclusion of subsequent threads.

2: How to use synchronized and volatile in multi-thread synchronization and mutual exclusion.

Now intercept a section of the problem that occurred during the execution of the above code and analyze how the problem occurred, and then use synchronized to solve the problem.

:Window 2…1
:Window 1…1
:Window 3…1
:Window 1…2
:Window 2…2
:Window 1… 3
:Window 3…2
:Window 1…4
:Window 2…3
:Window 1…5
:Window 3…3
:Window 1…6
:Window 2…4

The result of the above code is generated by implementing the Runnable interface. How did the above window 1, window 2, and window 3 generate 1 at the same time?

  int n=100;
  public void run() {
    while (true) {
    if (n > 0) {
System.out.println(":"Thread.currentThread().getName()
              + "..." + n--);
        } else {
          break;
        }
      }

This is the same piece of code executed by three threads. One reason for the above result may be that when window 2 finishes executing and outputs i=1, the virtual machine executes window 2 and window 2 executes Output I. At this time, i has not executed ++, so the value of i is still 1. At this time, the virtual machine gives the execution right to window 3. At this time, the i output by window 3 is still 1. The main reason for the above problem in the program The reason is that there is a public variable i, and the value of i is not synchronized during program execution. The above for loop body should be executed separately before other threads can seize the virtual machine. The Synchronized keyword is used to ensure that a thread is not preempted by other threads when executing a section of public resources.

The code block modified by synchronized is called synchronized code block, and the method modified by synchronized is called synchronized method. The ticket buying function is implemented by adding the synchronized keyword below:

class myRunnable implements Runnable {
  int n = 100;

  public void run() {
    while (true) {
      synchronized (this) {
        if (n > 0) {
          if (n % 10 == 0) {
            try {
              Thread.currentThread().sleep(10);
            } catch (InterruptedException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
            }
          }
          System.out.println(":" + Thread.currentThread().getName()
              + "..." + n--);
        } else {
          break;
        }
      }
    }
  }
}

public class ThreadTest {
  public static void main(String[] args) {
    myRunnable myrunnable = new myRunnable();
    Thread m1 = new Thread(myrunnable);
    Thread m2 = new Thread(myrunnable);
    Thread m3 = new Thread(myrunnable);
    m1.setName("窗口1");
    m2.setName("窗口2");
    m3.setName("窗口3");
    m1.start();
    m2.start();
    m3.start();
  }
}

At this time, the ticket selling function can be completed correctly.

上面代码中synchronized(this)中的this代表的是当前的对象,因为三个线程执行的都是myRunnable 的对象,所以三个线程公用的是同一个锁,其实这个this可以用任何的对象来代替,一般我们可以 String str=new String(“”);虽然str的值为空字符串,但是也是一个对象。Synchronized实现互斥的原理是每一个对象都有一个特定的变量值,当任何一个线程调用了synchronized想要进入公共资源区时,先判断该变量的值,若该变量的值为0则可以进入公共资源区,进程在进入公共资源区之前先把对象的中的该变量值变为1,出同步区后再将该变量的值变为0,从而实现线程互斥访问公共资源。

三:多线程的通讯中的notify(),notifyAll(),及wait(),的使用方法,以及简单的生成者和消费者的代码实现。

在讲解notify(),notifyAll(),wait()之前,先看看生产者和消费者问题:生产者生产面包,消费者消费面包,但是存放面包的容器有限,生产者一次最多只能生产20个面包,消费者每次在容器中拿一个面包。通过分析可以知道,当生产者生产了20个面包之后必须停下来,等容器里的面包数目小于20个时再继续生产,消费者看到容器里面面包个数为0时也必须停下来,等到有面包时才能消费。这时候就涉及到了生产者和消费者的通信。notify()是用于唤醒等待队列中的线程,wait()用于阻塞当前线程。Notify和wait()都必须用于synchronized修饰的同步代码块或同步方法中。

下面直接看生产者消费者代码。

class Consumer implements Runnable {
  Clerk clerk;
  Consumer(Clerk clerk) {
    this.clerk = clerk;
  }
  public void run() {
    while(true)
    clerk.consumeProduct();
  }
}
class Producter implements Runnable {
  Clerk clerk;
  Producter(Clerk clerk)
  {
    this.clerk = clerk;
  }
  public void run() {
    while(true)
    clerk.addProduct();
  }
}
class Clerk {
  int product ;
  public synchronized void consumeProduct() {
    while (true) {
      if (product <= 0) {
        try {
          wait();
        } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      } else {
        product--;
        notifyAll();
        System.out.println("消费者消费了:" + product);
      }
    }
  }
  public synchronized void addProduct() {
    if (product > 20) {
      try {
        wait();
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    } else {
      product++;
      notifyAll();
      System.out.println("生产者生产了:" + product);
    }
  }

}
public class Test {
  public static void main(String[] args) {
    Clerk clerk=new Clerk();
    Consumer consumer=new Consumer(clerk);
    Thread c=new Thread(consumer);
    Producter producter=new Producter(clerk);
    Thread p=new Thread(producter);
    c.start();
    p.start();
  }
}

【相关推荐】

1.Java免费视频教程

2.全面解析Java注解

3.阿里巴巴Java开发手册

The above is the detailed content of Briefly describe multi-thread implementation and synchronous mutual exclusion communication. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn