>  기사  >  Java  >  다중 스레드 구현 및 동기식 상호 배타적 통신을 간략하게 설명합니다.

다중 스레드 구현 및 동기식 상호 배타적 통신을 간략하게 설명합니다.

Y2J
Y2J원래의
2017-05-08 13:50:371040검색

다음 편집자는 Java 멀티스레딩 구현 및 동기식 상호 배제 통신에 대해 간략하게 설명합니다. 에디터가 꽤 좋다고 생각해서 지금 공유해서 참고용으로 올려보겠습니다. 편집기를 따라 살펴보겠습니다

Java 멀티스레딩에 대한 심층적인 이해이 글에서는 주로 세 가지 측면에서 멀티스레딩을 이해하고 마스터합니다.

1 . Thread 클래스를 상속하고 Runnable 인터페이스를 구현하는 멀티스레딩 구현과 유사점과 차이점.

2. 다중 스레드 동기화 및 상호 배제에서 동기화를 사용하는 방법.

3. 다중 스레드 통신에서 inform(), informAll() 및 wait()를 사용하는 방법과 간단한 생성기 및 소비자 코드 구현.

다음은 Java의 멀티스레딩에 대한 자세한 설명입니다.

1: 멀티스레딩 구현

Threa 클래스를 상속하여 멀티스레딩을 구현하는 것은 크게 다음 세 단계로 나뉩니다.

1단계: Thread를 상속하고 스레드 클래스.

2단계: Thread 하위 클래스의 인스턴스를 정의합니다.

3단계: Thread 클래스의 start() 메서드를 호출하여 스레드를 시작합니다.

다음은 간단한 코드 구현입니다.

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();
  }

}

위 스레드에서 사용된 여러 메서드: Thread.currentThraed().getName() 메서드는 현재 스레드의 이름을 가져옵니다. . mythread.setName("child thread");mythread 스레드의 이름을 "하위 스레드"로 바꿉니다.

Runnable 인터페이스를 구현하여 멀티스레딩을 구현하는 것은 주로 다음 단계로 나뉩니다.

1단계: Runnable에서 run(을 구현합니다. 인터페이스) 방법. Runnable의 인스턴스를 생성합니다.

2단계: Thread 클래스를 정의하고 위의 Runnable 인스턴스를 Thread 클래스의 생성자 메서드에 전달합니다.

3단계: Thread 클래스의 start() 메서드를 호출하여 스레드를 시작합니다.

다음은 간단한 코드 구현입니다.

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();
  }
}

Thread 클래스를 상속하고 Runnable 메소드를 구현하면 멀티스레딩이 가능하므로 두 가지 메소드는 무엇인가요? 차이점은 무엇입니까? 티켓 구매 카테고리를 통해 둘의 차이점을 살펴보겠습니다.

매표소에 총 100장의 티켓이 있고, 티켓 판매는 세 개의 창구를 통해 이루어진다고 가정해 보겠습니다. to open 세 가지 서로 다른 Thread가 티켓 구매에 사용됩니다. 먼저 Thread 클래스를 통해 티켓을 구매하는 방법을 살펴보겠습니다.

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();
  }
}

결과가 너무 길어서 표시하지 않겠습니다. 원래 세 개의 창구는 함께 100장의 티켓을 샀지만 결과적으로 각 창구는 n=100인 독립적인 객체 이기 때문에 이해하기 쉽습니다. 따라서 Thread 클래스를 통해 티켓 구매 기능을 구현하는 것은 실제로 불가능합니다. 실제로 Thread 메서드를 사용하여 각 스레드에서 실행되는 코드가 동일한 코드가 아닌 멀티스레딩을 구현합니다.

티켓 구매 기능을 구현하기 위해 Runnable 인터페이스를 구현하는 방법을 살펴보겠습니다.

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();
  }
}

위의 세 스레드는 동일한 하위 클래스를 공유하는 것을 볼 수 있습니다. Runnable 이므로 세 개의 스레드를 열어서 동일한 실행 가능 코드를 실행하면 됩니다. 그러니 300표를 사야하는 상황은 없을 것 같아요. 하지만 이 프로그램에는 여전히 문제가 있습니다. 후속 스레드의 동기화 및 상호 배제에 대해 논의한 후 이 프로그램을 개선하겠습니다.

2: 다중 스레드 동기화 및 상호 배제에서 동기화 및 휘발성을 사용하는 방법.

이제 위 코드 실행 중 발생한 문제의 한 부분을 가로채서 어떻게 문제가 발생했는지 분석한 후, 동기화를 이용하여 문제를 해결해 보세요.

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

위 코드의 결과는 Runnable 인터페이스를 구현하여 생성됩니다. 위의 창 1, 창 2, 창 3은 어떻게 동시에 1을 생성합니까?

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

이것은 세 개의 스레드에 의해 실행되는 동일한 코드 조각입니다. 위 결과의 한 가지 이유는 창 2가 실행을 마치고 i=1을 출력할 때 가상 머신이 창 2를 실행하고 창 2가 Output을 실행하기 때문일 수 있습니다. I. 이때 i는 ++를 실행하지 않았으므로 i의 값은 여전히 ​​1이다. 이때 가상머신은 윈도우 3에 실행권한을 준다. 이때 윈도우 3의 i 출력은 여전히 ​​1이다. .프로그램에서 위와 같은 문제가 발생하는 가장 큰 이유는 공개 변수 i가 있는데, 프로그램 실행 중에 i값이 동기화되지 않기 때문입니다. 위의 for 루프 본문은 다른 스레드가 가상 머신을 점유하기 전에 별도로 실행되어야 합니다. 동기화된 키워드는 공용 자원의 섹션을 실행할 때 스레드가 다른 스레드에 의해 선점되지 않도록 하는 데 사용됩니다.

동기화로 수정한 코드 블록을 동기화 코드 블록, 동기화로 수정한 방식을 동기화 방식이라고 합니다. 티켓 구매 기능은 아래 동기화 키워드

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();
  }
}

를 추가하여 구현됩니다. 이때 티켓 판매 기능은 올바르게 완료될 수 있습니다.

上面代码中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开发手册

위 내용은 다중 스레드 구현 및 동기식 상호 배타적 통신을 간략하게 설명합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.