一、概念
进程:它是运行中的程序。有的程序启动后可能有多个进程。Java程序的执行时,首先启动一个独立的JVM进程。该进程任务是解析并执行Java字节码。进程各有独立地址空间,JVM进程间不能访问对方所拥有内存空间。
线程:一个进程可以包含多个线程,但至少要包含一个线程。
二、线程 Thread类和Runnable接口
1.简介
类:java.lang.Thread 其代表可被JVM操控的线程。
接口:java.lang.Runnable 它不是线程,它可以通过覆写run()方法,编写执行任务的代码。可以将Runnable编写的对象传入Thread线程中。
换个说法来说,可以看作JVM为只有安装了一个主线程CPU的虚拟机,而创建Thread实例,为加装额外CPU,而Thread的start()为启动额外CPU,而run()内部为额外CPU所需要做的事。
2.常用方法
3.创建线程的两种方式
- 第一种方法:自定义类继承Thread类
- 1.覆写run()方法。
- 2.创建该类对象。
- 3.调用start()方法
- 实例:
class MyThread extends Thread{ public void run(){ for (int i = 0; i < 10; i++){ System.out.println(i); } } } public class test1{ public static void main (String[] args){ MyThread a = new MyThread(); a.start(); for (int j = 0; j < 100; j++){ System.out.println("test1.main()----"+j); } } }
- 第二种方法:自定义类继承Runnable接口
- 1.覆写run()方法。
- 2.创建实例对象。
- 3.添加到Thread对象内。
- 4.调用Thread对象的start()方法。
- 实例:
class MyThread implements Runnable{ public void run (){ for (int i = 0; i < 50; i++){ System.out.println(i); } } } public class test1{ public static void main (String[] args){ MyThread a = new MyThread(); Thread a1 = new Thread(a); a1.start(); } }
三、线程生命周期
1.默认方式
主线程从main()方法开始执行,直到main()方法结束停止JVM,如果主线程启动了额外线程,那就要等到所有线程都执行完run()方法才终止JVM。
2.Daemon线程
一个线程如果被标记为Deamon线程,当所有非Deamon线程都结束时,JVM就会自动终止。可以使用setDeamon()方法来设定线程是否为Deamon线程。可以使用isDeamon()方法来判断线程是否为Deamon线程。
默认从Deamon线程产生的线程也为Deamon线程,main方法默认为非Deamon线程。
3.Thread基本状态图
- 调用Thread实例start()方法后,线程状态变为Runnable可运行状态。此时线程还未开始执行run()方法。
- 排班器Schedule按照优先级排入CPU执行线程run(),优先级可利用setpriority()设置,范围为1(Thread.MIN_PRIORITY)~ 10(Thread.MAX_PRIORITY),默认为5(Thread.NORM_PRIORITY),超出范围会抛出IllegalArgumentException异常,数字越大,优先级越高,越先排入CPU。
- 当线程运行时碰到sleep(),锁,wait()等会让线程进入Blocked阻断状态,此时可以让其他线程进入CPU,提高运行效率。
4.安插线程
当一个线程A在执行时,线程B通过join()方法让线程A停下工作,让CPU先执行B线程的工作,等待B线程结束,才继续执行线程A的工作。
因此,Thread 的 join()方法让原来的线程停止,安插新线程工作,让优先级改变。可以给join指定参数,表示多少ms后停止的线程启动,不在管安插的新线程是否结束。
5.停止线程
线程运行完run()方法后,会进入Dead状态,进入此状态的线程不可再次使用start()启动,否则会报错。