Java基础笔记 - 线程介绍及其创建的两种方法 如何退出线程

1、线程与进程:

1.1、进程:

进程是操作系统结构的基础;是一个正在执行的程序;计算机中正在运行的程序实例;可以分配给处理器并由处理器执行的一个实体;由单一顺序的执行显示,一个当前状态和一组相关的系统资源所描述的活动单元。

1.2、线程:

线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。

1.3、线程和进程的区别:

进程的内部数据和状态是完全独立的,而多线程是共享一块内存空间和一组系统资源。

线程本社的数据通常只有寄存器数据和一个程序执行时使用的堆栈,所以线程的切换比进程切换的负担小。

1.4、单线程:

在没有特别的创建多线程的情况下,程序启动运行时,就自动产生一个线程,main方法就在这个主线程上运行。

1.5、多线程:

在一个程序中同时运行多个不同的线程执行不同的任务的机制。多线编程的目的是最大限度的利用CPU资源。

一个进程可以包含一个或多个线程。多个程序块交替运行时就需要产生多个线程。CPU随机分配执行线程。

2、Java中线程的实现的两种方式:

2.1、继承Thread类并重写run方法:

public class Thread
extends Object
implements Runnable

线程 是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程。

每个线程都有一个优先级,高优先级线程的执行优先于低优先级线程。每个线程都可以或不可以标记为一个守护程序。当某个线程中运行的代码创建一个新 Thread 对象时,该新线程的初始优先级被设定为创建线程的优先级,并且当且仅当创建线程是守护线程时,新线程才是守护程序。

Thread类中的常用方法:

void run()
如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。
Thread 的子类应该重写该方法。
void start()
使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
结果是两个线程并发地运行;当前线程(从调用返回给 start 方法)和另一个线程(执行其 run 方法)。
多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。

将我们希望执行的程序段放到run方法中,通过start方法启动线程,start方法首先为线程准备好系统资源,然后再调用run方法。

要想启动一个线程,唯一的方法是调用start()方法,如果直接调用run()方法就不能当成线程了,而是普通的调用一个run函数,一直执行下去。

对于单核的CPU多线程微观串行,宏观并行。而对于多核的CPU,可以实现微观上的并行。

下面继承Thread并重写run()方法创建线程类:

/*
\
线程类
*/
class MyThread extends Thread{

@Override
public void run() {
    for(int i=0; i<100; i++){
        System.out.println("number: " \+ i);
    }
}

}

在客户端创建并启动该线程:

public static void main(String[] args) {
MyThread thread = new MyThread();
//如果直接调用run函数,则并没有用线程启动,而是执行一个普通的函数
//thread.run();
//启动线程的唯一方法
thread.start();
}

2.2、通过定义实现Runnable接口的类进而实现run方法:

public interface Runnable

Runnable 接口应该由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为 run 的无参数方法。

run方法说明:

void run()
使用实现接口 Runnable 的对象创建一个线程时,启动该线程将导致在独立执行的线程中调用对象的 run 方法。
方法 run 的常规协定是,它可能执行任何所需的动作。

下面通过实现Runnable接口创建线程类:

/*
\
线程类
*/
class MyThread2 implements Runnable{

@Override
public void run() {
    for(int i=0; i<100; i++){
        System.out.println("number: " \+ i);
    }
}

}

在客户端调用:

public static void main(String[] args) {
MyThread2 mythread = new MyThread2();
//通过Runnable的实现类实例初始化一个Thread
Thread thread = new Thread(mythread);
//调用启动线程的唯一方法start()
thread.start();
}

显然,启动实现Runnable接口实现的线程类需要借助于Thread类,通过其构造函数:

Thread(Runnable target)
分配新的 Thread 对象。

2.3、两种线程实现方式的总结:

1、 两种实现方式均需要执行线程的start()方法为线程分配系统资源,调度线程运行并执行其run()方法。

2、 在实际的运用中,采用哪种方式根据实际情况而定,因为Java是单继承的,所以如果已经继承了一个类时,就只能通过实现Runnable接口创建线程类。

3、退出线程的方法:

线程的消亡不能通过调用stop()方法,而是让run()方法自然结束。

一般线程里面都是一个循环,为了退出线程,可以设置一个布尔类型的标志位,并作为循环条件,通过在run()方法中做一定的判断,满足条件时设置标志位为false,从而退出循环。

或者在满足条件时使用break语句退出。

arthinking wechat
欢迎关注itzhai公众号