>  기사  >  Java  >  Java에서 스레드를 이해하는 방법

Java에서 스레드를 이해하는 방법

王林
王林앞으로
2023-04-29 22:01:051128검색

Java에서 스레드를 이해하는 방법

스레드는 프로그램 내의 실행 경로입니다. 실제로는 프로그램에 실행 경로가 하나만 있는 경우 프로그램은 단일 스레드 프로그램입니다. 싱글 스레드가 있다면 멀티 스레딩도 있을 것입니다. 문자 그대로의 의미는 "싱글 스레딩에 비해 소프트웨어 및 하드웨어에서 여러 실행 프로세스를 수행하는 기술"로 이해될 수 있습니다. CPU 사용률. 다중 스레드 프로그램에서 하나의 스레드가 기다려야 할 때 CPU는 기다리는 대신 다른 스레드를 실행할 수 있어 프로그램의 효율성이 크게 향상됩니다.

멀티 스레드 생성

방법 1: Thread 클래스 상속

방법 1 생성 프로세스:

  • MyThread 하위 클래스를 정의하여 java.lang.Thread 스레드 클래스를 상속하고 run() 메서드를 재정의합니다.

  • MyThread 클래스의 개체를 만듭니다.
  • 스레드를 시작하려면 스레드 개체의 start() 메서드를 호출합니다(run() 메서드는 시작 후에도 계속 실행됩니다). 위 코드에서 실행되는 스레드, 즉 main 메서드의 메인 스레드와 스레드 객체mythread에서 start()를 호출하여 시작된 하위 스레드입니다. 그런데 왜 출력 결과가 고유하지 않습니까? 그 이유는 실행 중에 두 스레드 사이에 CPU 선점이 발생하고, 이를 먼저 점유한 사람이 먼저 실행되기 때문입니다.
  • 그렇다면 스레드 객체를 직접 사용하여 run() 메서드를 호출하면 어떨까요? run()을 직접 호출하면 그냥 일반적인 호출 메서드, 즉 단일 스레드가 되고, start() 메서드를 사용하면 자식 스레드를 시작하므로 멀티스레딩이 발생할 수 있습니다.
  • 방법 1의 장점과 단점:

장점: 간단한 코딩

    단점: 스레드 클래스는 Thread를 상속했으며 다른 클래스를 상속할 수 없으므로
  • 방법 2: Runnable 인터페이스
  • 메소드 구현 2. 생성 프로세스:

  • 1. Runnable 인터페이스를 구현하고 run() 메소드를 재정의하는 MyRunnable 객체를 생성합니다. 처리를 위해 MyRunnable 작업 개체를 Thread로 변환합니다.

Thread 생성자

method

public Thread(문자열 이름)

You 현재 스레드의 이름을 지정할 수 있습니다 이 코드와 메서드 1의 차이점은 MyRunnable 작업 개체를 Thread에 캡슐화해야 하며 다른 위치는 기본적으로 변경되지 않는다는 것입니다. 방법 2의 장점과 단점: 장점: 스레드 작업 클래스는 인터페이스만 구현하고 계속해서 클래스를 상속하고 인터페이스를 구현할 수 있습니다. 이는 확장성이 뛰어납니다. 단점: 스레드 작업 클래스에 추가 개체 패키징 계층이 있습니다. 프로그래밍 스레드에 실행 결과가 있으면 직접 반환할 수 없습니다. 다음으로 Runnable 인터페이스(익명 내부 클래스 형식)를 사용하여 다중 스레드를 생성합니다. 1. Runnable 익명 내부 클래스 객체를 생성합니다.
공용 스레드(실행 가능 대상) Runnable 개체를 스레드 개체로 캡슐화
공용 스레드(실행 가능 대상, 문자열 이름) Runnable 개체를 스레드로 캡슐화 개체를 지정하고 스레드 이름을 지정합니다
public class ThreadDemo01 {
    public static void main(String[] args) {
        MyThread myThread1 = new MyThread();
        myThread1.start();
        for (int i = 0; i < 3; i++) {
            System.out.println("主线程正在执行~~");
        }
    }
}
class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            System.out.println("子线程正在执行~~");
        }

    }
}
//输出结果(不唯一):
//主线程正在执行~~
//主线程正在执行~~
//主线程正在执行~~
//子线程正在执行~~
//子线程正在执行~~
//子线程正在执行~~

2 처리를 위해 이를 전달합니다. 스레드 개체 start()를 호출하면 스레드가 시작됩니다.

public class ThreadDemo02 {
    public static void main(String[] args) {
        MyRunnable target = new MyRunnable();
        Thread thread = new Thread(target);
        thread.start();
        for (int i = 0; i < 3; i++) {
            System.out.println("主线程正在执行~~");
        }
    }
}
class MyRunnable implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            System.out.println("子线程正在执行~~");
        }

    }
}
//输出结果(不唯一):
//主线程正在执行~~
//子线程正在执行~~
//子线程正在执行~~
//子线程正在执行~~
//主线程正在执行~~
//主线程正在执行~~

이 메서드에는 본질적으로 큰 차이가 없습니다. 하나는 스레드 개체를 만들어야 하고 다른 하나는 익명 내부 클래스를 통해 구현되는 멀티스레딩입니다. 그리고 이 코드 블록은 람다 표현식을 통해 간소화될 수도 있습니다. 이 지식 포인트에 여전히 깊은 인상을 받았는지 궁금합니다. 잊어버린 경우 다음 기사를 읽어보세요. Java에서 람다 표현식을 이해하는 방법 - 단순화됨

방법 3: 호출 가능 인터페이스 구현

멀티 스레드를 생성하는 이전 두 가지 방법을 연구한 후 문제가 있음을 발견하게 됩니다. : 1. 다시 작성된 run() 메서드는 결과를 직접 반환할 수 없습니다. 2. 스레드 실행 결과를 반환해야 하는 비즈니스 시나리오에는 적합하지 않습니다. 따라서 이러한 문제를 해결하려면 제3의 방법이 필요합니다.

메서드 3 생성 과정:

1. Callable 인터페이스를 구현하기 위한 클래스를 정의하고, call() 메소드를 다시 작성하고, 수행해야 할 작업을 캡슐화합니다.

2. FutureTask를 사용하여 Callable 객체를 스레드로 캡슐화합니다.

3. 스레드 작업 개체는 처리를 위해 Thread로 전달됩니다.

4. 스레드를 시작하고 작업을 실행하려면

5. , FutureTask의 get() 메소드를 통해 작업 실행 결과를 얻습니다.明 메소드 이름

설명 称Public Futuretask & LT & GT; (호출 가능 호출)

호출된 객체를 Futuretask 객체로

Public v Get()에서 예외 발생

반환된 결과

public class ThreadDemo03 {
    public static void main(String[] args) throws Exception {
        MyCallable myCallable = new MyCallable();
        FutureTask<String> futureTask = new FutureTask<>(myCallable);
        Thread thread = new Thread(futureTask);
        thread.start();
        int sum= 0;
        for (int i = 0; i < 3; i++) {
            sum+=i;
        }
        System.out.println(sum);
        String s =futureTask.get();
        System.out.println(s);
    }
}
class MyCallable implements Callable<String > {
    @Override
    public String call(){
        int sum=0;
        for (int i = 0; i < 3; i++) {
            sum+=i;
        }
        return "子线程计算结果:"+sum;
    }
}
//输出结果:
//3
//子线程计算结果:3

方式三优缺点:

优点:

线程任务类只是实现接口,可以继续继承类和实现接口,扩展性强;

可以在线程执行完毕后去获取 线程执行的结果;

缺点:

编码复杂一点;

总结

方式 优点 缺点
继承Thread类 编程比较简单,可以直接使用Thread类中的方法 扩展性较差,不能再继承其他的类,不能返回线程执行的结果
实现Runnable接口 扩展性强,实现该接口的同时还可以继承其他的类 编程相对复杂,不能返回线程执行的结果
实现Callable接口 扩展性强,实现该接口的同时还可以继承其他的类,可以得到线程的执行结果 编程相对复杂

常用方法

Thread获取和设置线程名称

方法名称 说明
String getName() 获取当前线程的名称,默认线程名称是Thread-索引
void setName(String name)

将此线程更改为指定的名称,通过构造器也可以设置线程名称

简单地通过一段代码让大家能够清晰地了解这个代码该如何使用:

public class ThreadDemo04 {
    public static void main(String[] args) throws Exception {
        thread thread1 = new thread();
        thread1.setName("1号子线程");
        thread1.start();
        thread thread2 = new thread();
        thread2.setName("2号子线程");
        thread2.start();
    }
}
class thread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            System.out.println(this.getName()+"正在执行任务"+i);
        }
    }
}
//输出结果:
//2号子线程正在执行任务0
//1号子线程正在执行任务0
//2号子线程正在执行任务1
//1号子线程正在执行任务1
//2号子线程正在执行任务2
//1号子线程正在执行任务2

Thread类的线程休眠方法

方法名称 说明
public static void sleep(long time) 让当前线程休眠指定的时间后再继续执行,单位为毫秒
public class ThreadDemo05 {
    public static void main(String[] args) throws Exception {
        for (int i = 0; i < 5; i++) {
            System.out.println(i);
            if (i==3){
                Thread.sleep(5000);
            }
        }
    }
}
//输出结果:
//1
//2
//3
//在输出过3以后,等待5秒之后再进行输出
//4

위 내용은 Java에서 스레드를 이해하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제