一、线程基础
1.线程的基本概念
- 程序:是一段静态的代码,是人们解决问题的思维方式在计算机中的描述,是软件执行的蓝本,它是一个静态概念。
- 进程:是程序的一个运行例程,是应用程序的一次动态执行过程。进程由若干个代码和数据块组成,每个进程还拥有其它的资源,例如文件、动态内存地址、线程等,进程是计算机进行资源分配的独立单位。
- 线程:是进程中相对独立的执行单元,是操作系统调度的基本单位,一个进程可以包含若干个线程。同一进程中的各个线程对应一组CPU指令、一组CPU寄存器以及一个堆栈。进程并不执行代码,它只是代码存放的地址空间。进程地址空间中存放的代码由线程来执行。线程的执行由操作系统负责调度。
2.线程的运行机制
JVM的很多任务都依赖线程调度,执行代码的任务是由线程来完成的。在Java中每一个线程都有一个独立的程序计数器和方法调用栈。
程序计数器:是一个记录当前执行代码的位置的寄存器,当线程在执行的过程中,程序计数器指向的是下一条要执行的指令。
方法调用栈:是用来描述线程在执行时一系列的方法调用过程。栈中的每个元素称为一个栈帧。每一个栈帧对应一个方法调用,帧中保存了方法调用的参数、局部变量和程序执行过程中的临时数据。
JVM进程被启动,在同一个JVM进程中,有且只有一个进程,就是它自己。然后在这个JVM环境中,所有程序的运行都是以线程来运行。JVM最先会产生一个主线程,由它来运行指定程序的入口点。在这个程序中,就是主线程从main方法开始运行。当main方法结束后,主线程运行完成。JVM进程也随之退出。
我们看到的是一个主线程在运行main方法,这样的只有一个线程执行程序逻辑的流程成为单线程。事实上,还可以在线程中创建新的线程并执行。这样在一个进程中就存在多个程序执行的流程,也就是多线程的环境。
主线程是JVM自己启动的,在这里它不是从线程对象产生的。在这个线程中,它运行了main方法这个指令序列,所以main方法应声明成静态的。
二、线程的创建和启动
线程需要创建然后执行
1.线程的创建
在Java中创建线程的方法有两种:Thread类和Runnable接口。在使用Runnable接口时需要建立Thread实例。因此,无论是通过Thread类还是Runnable接口建立线程,都必须建立Thread类或者它的子类的实例。
(1)继承Thread类
Thread类位于java.lang包中,Thread的每个实例对象就是一个线程,它的子类的实例也是一个线程。我们通过Thread类或者它的派生类才能创建线程实例并启动一个新的线程://它的构造方法
public Thread(ThreadGroup group,Runnable target,String name,long stackSize);
//group指明该线程所属的线程组,target为实际执行线程体的目标对象,
//name为线程名,stackSize为线程指定的堆栈大小。
//在创建线程时这些参数都可以没有。
我们编写Thread类的派生类,主要是覆盖方法run(),在这个方法中加入线程所要执行的代码即可,因此我们经常把run方法称为线程的执行体。
(2)实现Runnable接口
通过继承Thread类来创建线程,有一个缺点,那就是如果我们的类已经从一个类继承,则无法再继承Thread类。我们可以通过声明自己的类实现Runnable接口来创建线程。Runnable接口只有一个方法run(),我们声明的类需要实现这一方法。
实现Runnable接口来创建线程的步骤如下:
- 定义Runnable接口的实现类,并重写该接口的run方法。
- 创建Runnable实现类的实例,并以此实例作为Thread类的target参数来创建Thread线程对象,该Thread对象才是真正的线程对象。
/******实现Runnable接口创建多线程***********/
import java.util.*;
class TimePrinter implements Runnable
{
public boolean stop=false;
int pauseTime;
String name;
/*****构造函数初始化*****/
public TimePrinter(int x,String n){
pauseTime=x;
name=n;
}
public void run()
{
while(!stop)
{
try{
//在控制台显示当前系统的日期和时间;
System.out.println(name+":"+ new Date(System.currentTimeMillis()));
Thread.sleep(pauseTime);
}
catch(Exception e)
{
System.out.println(e);
}
}
}
}
public class NewThread2
{
static public void main(String args[])
{
TimePrinter tp=new TimePrinter(1000,"当前日期时间");
Thread t=new Thread(tp);//创建一个线程;
System.out.println("按回车键终止!");
try{
System.in.read();//从输入缓冲区中读取数据,按回车键返回;
}
catch(Exception e)
{
}
tp.stop=true;
}
}
2.线程的启动
创建一个线程对象后,仅仅在内存中出现了一个线程类的实例对象,线程并不会自动开始运行,必须调用线程对象的start()方法启动线程。它完成两个方面的功能:
- 为线程分配必要的资源,使线程处于可运行状态。
- 调用run方法来运行线程。
Thread ThreadName=new ThreadClass();
ThreadName.start();