> 일반적인 문제 > Java의 스레드를 이해하는 방법을 이해하는 기사

Java의 스레드를 이해하는 방법을 이해하는 기사

WBOY
풀어 주다: 2022-07-18 13:45:58
앞으로
1253명이 탐색했습니다.

이 기사에서는 주로 스레드와 관련된 문제를 정리하는 java에 대한 관련 지식을 제공합니다. 스레드는 프로그램 내의 실행 경로입니다. 실제로는 별도의 실행 경로만 있으면 됩니다. 프로그램에 하나의 실행 경로가 있다면 그 프로그램은 단일 스레드 프로그램임을 살펴보겠습니다. 이것이 모든 사람에게 도움이 되기를 바랍니다.

Java의 스레드를 이해하는 방법을 이해하는 기사

추천 학습: "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 인터페이스를 구현하기 위해 MyRunnable을 정의하고

2 MyRunnable 작업 객체를 생성합니다.

4. 스레드 개체 호출 start() 메서드는 스레드 생성자

method

현재 스레드의 이름을 지정할 수 있습니다. thread

public Thread(Runnable 대상)public Thread(Runnable 대상, 문자열 이름)
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("子线程正在执行~~");
        }

    }
}
//输出结果(不唯一):
//主线程正在执行~~
//子线程正在执行~~
//子线程正在执行~~
//子线程正在执行~~
//主线程正在执行~~
//主线程正在执行~~
로그인 후 복사

该代码与方式一的不同之处在于需要将MyRunnable任务对象封装在Thread中,其他的地方是基本上是没有变化的。

方式二优缺点:

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

缺点:编程多一层对象包装,如果线程有执行结果是不可以直接返回的。

接下来我们同样使用实现Runnable接口(匿名内部类形式)来实现多线程的创建:

1、创建Runnable匿名内部类对象;

2、交给Thread处理;

3、调用线程对象的start()启动线程;

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

//lambda简化版:
new Thread(()-> {
                for (int i = 0; i < 3; i++) {
                    System.out.println("子线程正在执行~~");
                }
        }).start();
로그인 후 복사

该种方法从本质上其实并没有太大的区别只不过是一个需要创建线程对象,而另一个则是通过匿名内部类实现的多线程。并且该块代码也可以通过lambda表达式进行精简,不知道大家是否还对这个知识点有印象呢?若忘记了可以看一下这篇文章:Java中的lambda表达式如何理解——精简

方式三:实现Callable接口

在学习过前面两种创建多线程的方式以后,我们会发现存在一个问题:1、重写的run()方法不能直接返回结果;2、不适合需要返回线程执行结果的业务场景。因此,我们需要第三种方式来解决这些问题。

方式三创建过程:

1、定义类实现Callable接口,重写call()方法,封装要做的事情;

2、用FutureTask把Callable对象封装成线程任务对象;

3、把线程任务对象交给Thread处理;

4、调用Thread的start()方法启动线程,执行任务;

5、线程执行完毕后,通过FutureTask的get()方法获取任务执行的结果。

Runnable을 캡슐화 객체는 스레드 객체가 됩니다
Runnable 객체를 캡슐화하여 스레드 객체가 되며 스레드를 지정합니다. 이름
方法名称说明
public FutureTask<>(Callable call)把Callable对象封装成FutureTask对象
public V get() throws Exception 获取线程执行call方法返回的结果
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视频教程

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

관련 라벨:
원천:csdn.net
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿