>  기사  >  Java  >  Java 스레드(1) - 스레드 상태 및 속성에 대한 자세한 설명

Java 스레드(1) - 스레드 상태 및 속성에 대한 자세한 설명

黄舟
黄舟원래의
2017-03-01 11:38:321566검색


운영 체제에서는 시분할 방식을 사용하여 CPU에서 여러 프로세스 작업을 지속적으로 전환하고 처리하므로 사람들에게 병렬 처리 느낌을 줍니다. 운영 체제 멀티태스킹. 멀티태스킹은 멀티스레딩의 개념을 하위 수준으로 확장합니다. 즉, 프로그램이 동시에 여러 스레드를 실행한다는 의미입니다. 동시에 두 개 이상의 스레드를 실행할 수 있는 이러한 종류의 프로그램을 다중 스레드 프로그램이라고 합니다.

(1) 스레드 생성

1. 스레드 인스턴스 생성

보는 것보다 보는 것이 좋다 자, 먼저 스레드에 대해 이야기해 보겠습니다. 다양한 상태, 새 스레드를 생성하는 방법을 직접 시연해 보는 것은 어떨까요?

package Thread;/**
 * 
 * @author QuinnNorris
 * 创建线程实例
 */public class NewThread {

    /**
     * @param args
     */
    public static void main(String[] args) {        // TODO Auto-generated method stub

        Runnable r = new Run();        //创建一个类对象
        Thread th = new Thread(r);        //由Runnable创建一个Thread对象
        th.start();        //调用start方法,运行新的线程,即运行的是th中的run方法
    }

}

Runnable 인터페이스를 구현하는 클래스인 Run을 살펴보겠습니다.

package Thread;/**
 * 
 * @author QuinnNorris
 * Run类实现了Runnable接口
 */public class Run implements Runnable {

    @Override
    public void run() {        // TODO Auto-generated method stub
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

스레드를 생성하고 실행하는 것은 아마도 먼저 Runnable 인터페이스를 구현하는 클래스를 생성하는 것입니다. 그 중 Runnable 인터페이스의 유일한 run 메소드가 구현되어 있습니다. 이 메소드는 스레드가 시작된 후 자동으로 호출됩니다. 그런 다음 메인 클래스에서 Run 클래스의 객체를 생성하고 이 객체를 생성자의 매개변수로 Thread 객체에 전달합니다. 그런 다음 Thread 객체의 매개변수로 start 메소드를 호출합니다. start 메소드는 자동으로 run 메소드를 호출합니다. 메서드에서 run.문 실행을 시작합니다. 이때 스레드가 생성되어 시작됩니다.

2.start 메소드 및 run 메소드

run 메소드는 새로운 스레드를 생성하지 않기 때문에 직접 호출할 수 없으며, 기존 스레드 중간에 start가 새 스레드를 생성하고 자동으로 run을 호출합니다. 어떤 상황에서도 run 메소드를 수동으로 호출할 필요가 없습니다.
그런데 API의 시작 메소드를 살펴보겠습니다.

public void start( )
스레드 실행을 시작합니다.
JVM(Java Virtual Machine)은 스레드의 실행 메소드를 호출합니다.
결과적으로 두 개의 스레드가 동시에 실행됩니다. 즉, 현재 스레드(start 메서드 호출에서 반환)와 다른 스레드(run 메서드 실행)입니다.
스레드를 여러 번 시작하는 것은 불법입니다. 특히 스레드 실행이 끝나면 다시 시작할 수 없습니다.

3.Runnable 클래스

우리는 이미 스레드를 만드는 방법을 단계별로 알고 있지만 이것이 우리의 호기심을 충족시키지는 못합니다. 이 두 클래스를 자세히 살펴보고 어떤 메서드와 속성이 포함되어 있는지 확인하세요. Runnable 클래스에는 속성이 없으며 실행 메서드는 하나만 있습니다. 이 인터페이스는 스레드를 통해 인스턴스를 실행하려는 클래스에 의해 구현되어야 합니다. Thread 클래스는 더 복잡합니다.

(2) Thread 클래스

1. Thread 클래스는 Runnable 인터페이스를 구현합니다.

그래서 위의 예에서는 Run 클래스에는 Thread가 Runnable을 구현하기 때문에 자연스러운 작성 방법은 Thread 클래스를 상속하는 것입니다. 하지만 인터뷰 질문은 다음과 같은 질문을 많이 던집니다. 멀티스레딩을 구현하는 두 가지 방법 중 Thread 또는 Runnable 중 어느 것이 더 낫습니까? 이때 Runnable 메소드에 응답해야 합니다. 그 이유도 매우 간단합니다. 상속은 하나만 있을 수 있지만 인터페이스는 여러 개 있을 수 있습니다. Runnable은 이 클래스의 상속의 유연성을 방해하지 않는 인터페이스입니다.

2. Thread 생성자

Thread에는 많은 생성자가 있으며 주로 4개의 매개변수가 있습니다.

public Thread(ThreadGroup group,Runnable target, String name,long stackSize)

다른 생성자는 다음과 같습니다. 그러면 이 네 가지 매개변수의 의미를 살펴보겠습니다.

1. ThreadGroup 그룹

ThreadGroup은 스레드 그룹을 의미하며, 스레드 그룹을 분류하고 관리할 수 있습니다. 스레드 배치. 스레드 그룹을 제어하고 관리한다는 것은 스레드 그룹의 스레드 배치를 동시에 제어하는 ​​것을 의미합니다. 사용자가 생성한 모든 스레드는 지정된 스레드 그룹에 속합니다. 지정된 스레드 그룹이 표시되지 않으면 해당 스레드는 기본 스레드 그룹(즉, 메인 스레드 그룹)에 속합니다. 기본적으로 하위 스레드와 상위 스레드는 동일한 스레드 그룹에 있습니다. 스레드가 속한 스레드 그룹은 스레드가 생성될 때만 지정할 수 있습니다. 즉, 스레드가 속한 스레드 그룹을 지정하면 변경할 수 없습니다. 스레드가 끝날 때까지 변경되지 않습니다. 스레드 그룹과 스레드 간의 구조는 트리 구조와 유사합니다. 스레드는 자신의 스레드 그룹 정보에만 액세스할 수 있고 상위 스레드 그룹이나 다른 스레드 그룹의 정보에는 액세스할 수 없습니다.

2.Runnable target

target은 run 메소드가 호출되는 객체입니다. 이 매개변수가 null이면 Thread 클래스에서 run 메소드를 다시 작성해야 합니다. 그렇지 않으면 Thread 클래스의 run 메소드가 Runnable 클래스의 run 메소드를 호출합니다.

3.문자열 이름

실제로 이 매개변수는 스레드 이름을 지정하는 경우가 거의 없습니다. . 하지만 이 매개변수를 입력하지 않으면 스레드가 자동으로 새 이름을 생성합니다. 자동으로 생성된 이름은 "Thread-"+n 형식입니다. 여기서 n은 정수입니다.

4.long stackSize

这是一种具有平台依赖性的参数,stackSize能指定堆栈的大小。 在某些平台上,指定一个较高的 stackSize 参数值可能使线程在抛出 StackOverflowError 之前达到较大的递归深度。stackSize 参数的值与最大递归深度和并发程度之间的关系细节与平台有关。在某些平台上,stackSize 参数的值无论如何不会起任何作用。 作为建议,可以让虚拟机自由处理 stackSize 参数。

Thread中还有很多很多实用的方法,我们在涉及到具体概念的时候再给予介绍。

(三)中断线程

我们既然创建了线程,那么这个线程在什么时候终止呢?有两种情况:

  1. 当线程的run方法执行方法体中最后一条语句后,正常退出而自然死亡。

  2. 出现了在方法中没有捕获的异常,此时终止run方法,意外死亡。

从这两点中,我们可以看出,其实我们并没有特殊的手段可以人为的去在中间干涉线程的中断(Thread中的stop方法或许有这种作用,但是这个方法已经被废弃,我们不要使用它)。虽然没有强制结束线程的方法,但是我们可以用interrupt方法请求终止线程。要注意“请求”这个词,没有任何语言方面的表述是要求一个被中断的线程应该被终止。我们去用interrupt方法中断一个线程不过是引起他的注意。被中断的线程可以决定如何去响应这个中断的请求。

当对一个线程调用interrupt方法时,线程的中断状态将被置位。这个中断状态是每个线程都有的boolean标志。每个线程都会不时地检查这个布尔值,判断这个线程是否被中断。
我们可以使用:

Thread.currentThread().isIntertrupted()

isInterrupt方法和interrupt很像,它是用来判断线程是否被中断。
我们可以通过interrupt方法来中断一个线程,但是值得注意的是,如果这个线程处于wait和sleep或者在join方法调用过程中,中断线程将会报一个InterruptedException异常,我们可以通过try-catch块来捕获这种异常。

(四)线程状态

线程一共有6种状态,这六种状态不是我们规定的,而是在Thread中的内部嵌套类State中规定的。这六种状态分别是New,Runnable,Blocked,Waiting,Timed waiting,Terminated六种,我们来逐个分析一下这几种状态的含义:

1.New 新创建的线程

这里的创建新的线程真的是仅仅new了一个线程。

new Thread(r);

创建新的线程,是指刚刚new出来的线程,这个线程没有通过start的方法来启动。

2.Runnable 可运行

那么一旦我们调用了start方法,这个线程开始工作。这是他就处于可运行状态,这个可运行状态不只是包含线程运行的时候,线程在中断的时候也被算为可运行状态。一个可运行状态的线程可能在运行也可能没在运行,我们不要因为一个线程在可运行的状态下没运行而急躁,很有可能这个线程的终止只是为了让其他的线程获得机会。

3.Blocked 被阻塞

当一个线程试图去获得一个内部锁时,但这个内部锁被其他的线程持有,这个时候,为了等待去使用这个内部锁,这个线程将会暂时处在被阻塞的状态。当其他线程释放锁的时候,这个线程获得了内部锁,并且从阻塞状态转变为非阻塞状态。

4.Wait 等待

当一个线程等待另一个线程通知调度器一个条件时,这个线程自己进入等待状态。等待状态和阻塞状态很类似,但是他们是存在本质区别的。如果另一个线程通知调度器结束,那么这个线程进行工作,等待状态也随之结束。

5.Timed waiting 计时等待

计时等待和等待是比较相似的,计时等待是表示他有一个超时参数。调用他们导致线程会进入计时等待。这个状态将一直保持到超市期满或者接收到适当的通知。相比较直接的等待,变得更加的安全。

6.Terminated 终止

线程的终止,我们在上面的线程中断中有所提及。线程终止理论上只有两种情况:当线程的run方法执行方法体中最后一条语句后,正常退出而自然死亡。2. 出现了在方法中没有捕获的异常,此时终止run方法,意外死亡。

(五)线程属性

线程中有很多的属性,尽管我在API中只看到一些其中一小部分的字段,但是线程的这种理念,在方法中也有所体现。线程的属性有以下这些:线程优先级,守护线程,处理未捕获异常的处理器。

1.线程优先级

在java中,每个线程都有一个优先级,我们需要知道的是,在没经过特殊处理的时候,所有的线程优先级都是一样的。默认的,我们把优先级分成1到10之间,高优先级的线程会先被操作。说到这里不由得让我们想起了操作系统中的进程优先级,和一些类似老化这样的名词。实际上,java虚拟机也确实是用进程的优先级来类比出线程的优先级,这样做最大的一个问题就在于,每个操作系统对于进程优先级的处理并不相同,java的线程优先级也因此而具有平台变化。实际上,我们不应该把程序的正确性依赖于线程优先级,我们应该尽量少的使用线程优先级。我们在这里介绍了线程优先级,但是我们并不建议去使用它。

2.守护线程

守护线程是指通过:

t.setDaemon(ture); //将线程转换为守护线程

这样的写法,将一个线程转换为守护线程。守护线程的作用是为其他的线程提供服务,如果其他所有的线程都被退出,只剩下守护线程,那么程序也就结束了。没有去单独运行守护线程的必要。比如说其他线程的计时器,我们就可以将它设置为一个守护线程。

3.处理未捕获异常的处理器

run方法不能抛出任何被检查,不被检测的异常会导致线程终止。在这种情况下,线程就死亡了。在这种情况下,我们需要实现一个Thread.UncaughtExceptionHandler。我们可以通过这种方式来知道,真正让我们的run意外死亡的问题在哪里。

(六)总结

在java的并发程序中,我们先了解了这些线程的状态和属性,下面我们就可以来研究关于线程之间同步的问题。如何能几个线程同时运行,让他们之间配合的好。

在操作系统中,我们通过分时的方法在CPU上不断地切换处理多个进程任务,给人并行处理的感觉,这种方法在操作系统中叫做多任务。多任务在较低层次上扩展出多线程的概念,也就是指一个程序同时执行多个线程。这种可以同时运行一个以上的线程的程序,我们叫做多线程程序。

 以上就是java线程(一)—线程状态及属性详解的内容,更多相关内容请关注PHP中文网(www.php.cn)!


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