线程的概念:
线程是一个程序里面不同的执行路径!
public class ThreadTest01 {
public static void main(String[] args){
m1();
}
public static void m1(){
m2();
m3();
}
public static void m2(){
}
public static void m3(){
}
}
上面这个小程序的执行路径是先调用主线程main,main调用m1方法,m1里调用m2,等m2执行完之后,掉m3,等m3执行结
束,m1执行完,main接着向下执行完。
上面这个程序的执行路径只有一条!
main方法是一个主线程。每一个分支(路径)就是一个线程。
进程是一个静态的概念。机器上的一个class文件,一个.exe文件。一个程序的执行过程是这样的:
首先要将代码加载到内存中,具体是代码区里。到这一步,进程已经产生了!!!但是并没有开始执行!!!
进程的开始是指进程的主线程(或main方法)的执行!实际上运行的都是线程!!!
#######################################################################################
介绍完线程的概念之后,了解下Java中怎么使用线程。
Java中线程是java.lang.Thread类来实现的。
可以通过创建Thread的实例来创建新的线程。
每个线程都是通过某个特定Thread对象所对象的方法run()来完成其操作的,方法run()称为线程体。
通过调用Thread类的start()方法来启动一个线程。
@可以有两种方式创建新的线程。
第一种:
定义线程类实现Runnable接口。
Thread myThread = new Thread(target) // target为Runnable接口类型。
使用Runnable接口可以为多个线程提供共享的数据。
在实现Runnable接口的类的run方法定义中可以使用Thread的静态方法:
public static Thread currentThread() 获取当前线程的引用。
第二种:
可以定义一个Thread的子类并重写run方法如:
class MyThread extends Thread{
public void run(){....}
}
然后生成该类的对象:
MyThread myThread = new MyThread(...)
直接使用run方法和start方法的区别:
方法1:
public class CreateThreadMethod01 {
public static void main(String[] args){
Runner1 r1 = new Runner1();
Thread t = new Thread(r1);
t.start();
for(int i=0;i<1000;i++){
System.out.println("小李"+i);
}
}
}
class Runner1 implements Runnable{
@Override
public void run() {
for(int i=0;i<1000;i++){
System.out.println("小王"+i);
}
}
}
输出结果:
小李0
wang0
小李1
wang1
小李2
wang2
小李3
小李4
小李5
小李6
小李7
小李8
wang3
小李9
wang4
小李10
wang5
小李11
小李12
小李13
wang6
小李14
程序的执行路径是这样的:
因为新起了一个线程,会在main主线程和runner1子线程之间交替地执行。
如果把程序改成这样:
public class CreateThreadMethod01 {
public static void main(String[] args){
Runner1 r1 = new Runner1();
r1.run();//这样是方法调用,而不是起个新线程!!!
// Thread t = new Thread(r1);
// t.start();
for(int i=0;i<1000;i++){
System.out.println("小李"+i);
}
}
}
class Runner1 implements Runnable{
@Override
public void run() {
for(int i=0;i<1000;i++){
System.out.println("wang"+i);
}
}
}
由于上面相当于直接调用run方法,程序的执行过程是这样的:
先执行main主线程,main调用run方法,等待run执行完,然后接着执行下面的程序。程序的输出结果是这样的:
。。。。
wang994
wang995
wang996
wang997
wang998
wang999
小李0
小李1
小李2
小李3
小李4
小李5
小李6
小李7
小李8
小李9
小李10
小李11
小李12
。。。
线程启动必须调用Thread类的start方法,start方法会通知CPU有时间给它的线程一些时间片。
方法二:
public class CreateThreadMethod02 {
public static void main(String[] args){
Runner2 r = new Runner2();
r.start();
for(int i=0;i<1000;i++){
System.out.println("李四"+i);
}
}
}
class Runner2 extends Thread {
public void run(){
for(int i=0;i<1000;i++){
System.out.println("wang"+i);
}
}
}
比较这两种方法,方法1实现Runnable接口要更为灵活,因为直接继承Thread就不能继承别的类了。而实现接口还可以继承其他的类。