>  기사  >  Java  >  Java에서 멀티스레딩을 구축하는 세 가지 방법 공유

Java에서 멀티스레딩을 구축하는 세 가지 방법 공유

黄舟
黄舟원래의
2017-09-18 09:37:351316검색

이 글에서는 자바 멀티스레딩의 세 가지 구축 방법에 대한 관련 정보를 주로 소개합니다. 다음은 세 가지 구현 방법입니다. 모두가 매우 중요한 기본 지식을 습득할 수 있기를 바랍니다.

자바 멀티스레딩 세 가지 생성 방법

Thread 클래스를 상속하여 스레드 클래스 생성


public class Thread extends Object implements Runnable
  1. Thread 클래스의 하위 클래스를 정의하고 run() 메서드를 재정의

  2. Thread 하위 클래스의 인스턴스를 생성합니다. 그것은 스레드 객체를 생성했습니다

  3. 스레드 객체의 start() 메소드를 호출하여 스레드를 시작합니다


public class FirstThread extends Thread {
  public void run(){
    for(int i=0;i<100;i++){
      /*
       * Thread类已经继承了Object
       * Object类创建了name选项 并且有其getName(),setName()方法
       * 在继承Thread的类里面使用时只需要用this引用
      */
      System.out.println(this.getName()+" "+i);
    }
  }

  public static void main(String[] args) {
    for(int i=0;i<100;i++){
      System.out.println(Thread.currentThread().getName()+" "+i);
      if(i==20){
        new FirstThread().start();
        new FirstThread().start();
      }
    }
  }

}

Thread 클래스가 Object를 상속받았습니다

Object 클래스가 name 옵션을 생성했습니다 getName(), setName() 메서드가 있습니다

Thread를 상속하는 클래스에서 사용할 때는 이 참조만 사용하면 됩니다

위의 두 보조 스레드와 메인 스레드는 무작위로 전환되며, 상속하는 클래스가 스레드를 사용하면 두 개의 보조 스레드가 리소스를 공유할 수 없습니다

start() 메서드가 호출된 후 멀티 스레드 코드는 즉시 실행되지 않지만 스레드 프로그래밍은 실행 가능하게 됩니다. 실행 시기는 운영 체제에 의해 결정됩니다.

Runnable 인터페이스를 구현하여 스레드 클래스 생성


public Thread() 
public Thread(Runnable target) 
public Thread(Runnable target,String name)
  • Runnable 인터페이스의 구현 클래스를 정의하고 인터페이스의 run() 메서드를 재정의합니다.

  • 실행 가능한 구현 클래스를 사용하여 Thread 개체를 생성합니다. Thread 개체는 실제 스레드 개체입니다.


public class SecondThread implements Runnable {
  public void run(){
    for(int i=0;i<100;i++){
      System.out.println(Thread.currentThread().getName()+" "+i);
    }
  }

  public static void main(String[] args) {
    for(int i=0;i<100;i++){
      System.out.println(Thread.currentThread().getName()+" "+i);

      if(i==20){
        SecondThread st=new SecondThread();
        //通过new Thread(target,name)创建线程
        new Thread(st,"新线程1").start();
        new Thread(st,"新线程2").start();
      }
    }
  }
}

위 결과는 두 개의 보조 스레드와 메인 스레드가 무작위로 전환되지만 공유할 리소스가 전혀 없기 때문에 공유 리소스가 없다는 것입니다.

start() 메서드가 호출된 후 멀티 스레드 코드가 즉시 실행되지는 않지만 스레드 프로그래밍을 실행 가능하게 만드는 시점은 운영 체제에 따라 결정됩니다.
Thread 클래스를 상속하는 공유 리소스에 대한 자세한 설명 Runnable 인터페이스를 생성합니다

공유할 수 있는 리소스만 있는 경우 동일한 인스턴스화 개체가 사용됩니다. 두 가지 생성 방법은 리소스를 공유할 때만 다르며, 그렇지 않으면 리소스를 공유하지 않습니다. 공유 리소스는 일반적으로 private static 수정자를 사용하여 수정됩니다.


class Thread1 extends Thread{ 
  private int count=5; 
  private String name; 
  public Thread1(String name) { 
    this.name=name; 
  } 
  public void run() { 
    for (int i = 0; i < 5; i++) { 
      System.out.println(name + "运行 count= " + count--); 
      try { 
        sleep((int) Math.random() * 10); 
      } catch (InterruptedException e) { 
        e.printStackTrace(); 
      } 
    } 

  } 
} 

public class Main { 

  public static void main(String[] args) { 
    Thread1 mTh1=new Thread1("A"); 
    Thread1 mTh2=new Thread1("B"); 
    mTh1.start(); 
    mTh2.start(); 

  } 

}


B运行 count= 5 
A运行 count= 5 
B运行 count= 4 
B运行 count= 3 
B运行 count= 2 
B运行 count= 1 
A运行 count= 4 
A运行 count= 3 
A运行 count= 2 
A运行 count= 1

공유 리소스가 있는 것은 바로 private int count=5; 문장 때문이지만 이는 Thread 클래스를 상속하는 하위 클래스이므로 리소스를 공유할 수 없습니다


class Thread2 implements Runnable{ 
  private int count=15; 
  public void run() { 
     for (int i = 0; i < 5; i++) { 
       System.out.println(Thread.currentThread().getName() + "运行 count= " + count--); 
        try { 
          Thread.sleep((int) Math.random() * 10); 
        } catch (InterruptedException e) { 
          e.printStackTrace(); 
        } 
      } 

  } 

} 
public class Main { 

  public static void main(String[] args) { 

    Thread2 my = new Thread2(); 
      new Thread(my, "C").start();//同一个mt,但是在Thread中就不可以,如果用同一个实例化对象mt,就会出现异常   
      new Thread(my, "D").start(); 
      new Thread(my, "E").start(); 
  } 

}


C运行 count= 15 
D运行 count= 14 
E运行 count= 13 
D运行 count= 12 
D运行 count= 10 
D运行 count= 9 
D运行 count= 8 
C运行 count= 11 
E运行 count= 12 
C运行 count= 7 
E运行 count= 6 
C运行 count= 5 
E运行 count= 4 
C运行 count= 3 
E运行 count= 2

마찬가지로, Runnable을 구현하는 클래스가 리소스를 공유할 수 있는 것은 바로 private int count=15라는 공통 인스턴스화 개체 때문입니다

그러면 Thread 클래스를 상속하는 하위 클래스와 Thread 클래스를 구현하는 클래스 간에 리소스 공유에 차이가 있는 이유는 무엇입니까? 실행 가능한 인터페이스?

Java는 단일 상속만 지원할 수 있기 때문에 단일 상속 기능은 하나의 하위 클래스만 상속할 수 있고 Runnabl 인터페이스 뒤에 여러 클래스가 올 수 있으므로 여러 스레드가 리소스를 공유할 수 있음을 의미합니다.

Callable 및 Future create 사용 thread

Callable은 Runnable 인터페이스의 향상된 버전처럼 보입니다. Callable에는 Runnable의 run() 메서드와 동일한 call() 메서드가 있지만 기능이 더 강력합니다.

call() 메서드는 반환 값을 가질 수 있습니다.
call() 메소드는 예외 발생을 선언할 수 있습니다.

Callable 인터페이스에는 일반적인 제한 사항이 있습니다. Callable 인터페이스의 일반 매개변수 유형은 call() 메소드의 반환 값 유형과 동일합니다. 또한 Callable 인터페이스는 기능적 인터페이스이므로 Lambda 표현식을 사용하여 Callable 객체를 생성할 수 있습니다. Runnable 인터페이스도 기능적 인터페이스이므로 Lambda 표현식을 사용하여 Runnable 객체를 생성할 수도 있습니다. Callable 인터페이스의 구현 클래스와 call() 메소드를 구현하면 call() 메소드가 스레드 실행 본문으로 사용된 다음 Callable 구현 클래스의 인스턴스를 생성합니다

    FutureTask 클래스를 사용하여 Callable 객체를 래핑합니다. , FutureTask 개체는 Callable 개체의 call() 메서드를 캡슐화합니다
  1. FutureTask 클래스 개체를 Thread 개체의 대상으로 사용하여 새 스레드를 만들고 시작합니다.
  2. FutureTask의 get() 메서드를 호출합니다. 하위 스레드가 끝난 후 반환 값을 가져오는 객체

  3. public class ThirdThread implements Callable<Integer> {
      public Integer call(){
        int i=0;
        for(;i<100;i++){
          System.out.println(Thread.currentThread().getName()+" "+i);
        }
        return i;
      }
    
      public static void main(String[] args){
        ThirdThread tt=new ThirdThread();
        FutureTask<Integer> task=new FutureTask<>(tt);
        Thread t=new Thread(task,"有返回值的线程");
        for(int i=0;i<100;i++){
          System.out.println(Thread.currentThread().getName()+" "+i);
          if(i==20){
            t.start();
          }
        }
        try{
          System.out.println("返回值是:"+task.get());
        }catch(Exception e){
          e.printStackTrace();
        }
      }
    }

  4. 람다 표현식 사용 Callable 및 Future에서 생성된 스레드


public class ThirdThread{
  public static void main(String[] args){
    ThirdThread tt=new ThirdThread();
    //先使用Lambda表达式创建Callable<Integer>对象
    //使用FutureTask封装Callable对象
    FutureTask<Integer> task=new FutureTask<Integer>((Callable<Integer>)()->{
      int i=0;
      for(;i<100;i++){
        System.out.println(Thread.currentThread().getName()+"的循环变量i的值:"+i);
      }
      return i;
    });

    for(int i=0;i<100;i++){
      System.out.println(Thread.currentThread().getName()+"的循环变量i的值:"+i);
      if(i==20){
        new Thread(task,"有返回值的线程").start();
      }
    }
    try{
      System.out.println("子线程的返回值"+task.get());
    }catch(Exception e){
      e.printStackTrace();
    }
  }
}

위 내용은 Java에서 멀티스레딩을 구축하는 세 가지 방법 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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