Java多线程start()函数和run()函数

在Java中,线程通常有五种状态:创建,就绪,运行,阻塞和死亡。

创建状态:在生成线程对象,并没有调用该对象的star方法,这时线程处于创建状态。

就绪状态:当调用了线程对象的start方法之后,该线程就进入就绪状态。但是此时线程调度程序还没有把该线程设置

                为当前线程,此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。

运行状态:线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数中的代码。

阻塞状态:线程正在运行的时候,被暂停 ,通常是为了等待某个事件的发生之后再运行。sleep,suspend,wait等方法

                 都可以导致线程阻塞。

死亡状态:如果一个线程的run方法执行结束或者被调用stop方法后,该线程就会死亡。对于死亡的线程,无法再使用start方法

               令其进入就绪。

实现线程的方法

    Java中实现并启动线程有两种方法:

    1.写一个类继承Thread类,重写run方法,用start方法启动线程。

    2.写一个类实现Runnable接口,实现run方法。用new Thread(Runnable target).start()方法来启动。

start()方法   

    用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行run()方法,这里方法 run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止。

run()方法

    run()方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到写线程的目的。总结:调用start方法方可启动线程,而run方法只是thread的一个普通方法调用,还是在主线程里执行。这两个方法应该都比较熟悉,把需要并行处理的代码放在run()方法中,start()方法启动线程将自动调用 run()方法,这是由jvm的内存机制规定的。并且run()方法必须是public访问权限,返回值类型为void。

    Thread的子类要重写这个方法,通过Thread调用run()方法,执行线程的线程体。

调用start()后,线程会被放到等待队列,等待CPU调度,并不一定要马上开始执行,只是将这个线程置于可动行状态。然后通过JVM,线程Thread会调用run()方法,执行本线程的线程体。先调用start后调用run,这么麻烦,为了不直接调用run?就是为了实现多线程的优点,没这个start不行。

多线程就是分时利用CPU,宏观上让所有线程一起执行 ,也叫并发

public class Test1 {
    public static void main(String[] args) {
    	ThreadTest1 t1 = new ThreadTest1();
    	ThreadTest2 t2 = new ThreadTest2();

        Thread thread1 = new Thread(t1);
        Thread thread2 = new Thread(t2);
        thread1.start(); 
        thread2.start();
    }
}

class ThreadTest1 implements Runnable { 
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("ThreadTest1正在运行==========" + i);
        }
    }
}

class ThreadTest2 implements Runnable { 
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("ThreadTest2正在运行==========" + i);
        }
    }
}

从执行结果来看,ThreadTest1和ThreadTest2是交叉执行,即并发执行的。

ThreadTest1正在运行==========0
ThreadTest2正在运行==========0
ThreadTest1正在运行==========1
ThreadTest2正在运行==========1
ThreadTest2正在运行==========2
ThreadTest2正在运行==========3
ThreadTest2正在运行==========4
ThreadTest2正在运行==========5
ThreadTest2正在运行==========6
ThreadTest2正在运行==========7
ThreadTest2正在运行==========8
ThreadTest2正在运行==========9
ThreadTest2正在运行==========10
ThreadTest2正在运行==========11
ThreadTest2正在运行==========12
ThreadTest1正在运行==========2
ThreadTest1正在运行==========3
ThreadTest1正在运行==========4
ThreadTest1正在运行==========5
ThreadTest2正在运行==========13
ThreadTest2正在运行==========14
ThreadTest2正在运行==========15
ThreadTest2正在运行==========16
ThreadTest2正在运行==========17
ThreadTest2正在运行==========18
ThreadTest1正在运行==========6
ThreadTest2正在运行==========19
ThreadTest1正在运行==========7
ThreadTest1正在运行==========8
ThreadTest1正在运行==========9
ThreadTest1正在运行==========10
ThreadTest1正在运行==========11
ThreadTest1正在运行==========12
ThreadTest1正在运行==========13
ThreadTest1正在运行==========14
ThreadTest1正在运行==========15
ThreadTest1正在运行==========16
ThreadTest1正在运行==========17
ThreadTest1正在运行==========18
ThreadTest1正在运行==========19

public class Test1 {
    public static void main(String[] args) {
    	ThreadTest1 t1 = new ThreadTest1();
    	ThreadTest2 t2 = new ThreadTest2();
        Thread thread1 = new Thread(t1);
        Thread thread2 = new Thread(t2);
        thread1.run(); 
        thread2.run();
    }
}

class ThreadTest1 implements Runnable { 
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("ThreadTest1正在运行==========" + i);
        }
    }
}


class ThreadTest2 implements Runnable { 
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("ThreadTest2正在运行==========" + i);
        }
    }
}

从运行结果来看,ThreadTest1和ThreadTest2是顺序执行的。

ThreadTest1正在运行==========0
ThreadTest1正在运行==========1
ThreadTest1正在运行==========2
ThreadTest1正在运行==========3
ThreadTest1正在运行==========4
ThreadTest1正在运行==========5
ThreadTest1正在运行==========6
ThreadTest1正在运行==========7
ThreadTest1正在运行==========8
ThreadTest1正在运行==========9
ThreadTest1正在运行==========10
ThreadTest1正在运行==========11
ThreadTest1正在运行==========12
ThreadTest1正在运行==========13
ThreadTest1正在运行==========14
ThreadTest1正在运行==========15
ThreadTest1正在运行==========16
ThreadTest1正在运行==========17
ThreadTest1正在运行==========18
ThreadTest1正在运行==========19
ThreadTest2正在运行==========0
ThreadTest2正在运行==========1
ThreadTest2正在运行==========2
ThreadTest2正在运行==========3
ThreadTest2正在运行==========4
ThreadTest2正在运行==========5
ThreadTest2正在运行==========6
ThreadTest2正在运行==========7
ThreadTest2正在运行==========8
ThreadTest2正在运行==========9
ThreadTest2正在运行==========10
ThreadTest2正在运行==========11
ThreadTest2正在运行==========12
ThreadTest2正在运行==========13
ThreadTest2正在运行==========14
ThreadTest2正在运行==========15
ThreadTest2正在运行==========16
ThreadTest2正在运行==========17
ThreadTest2正在运行==========18
ThreadTest2正在运行==========19


实现Runnable接口所具有的优势:

1.避免Java单继承的问题。

2.适合多线程处理同一个资源。

3.代码可以被多线程共享,数据独立,很容易实现资源共享。

4.线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类

  • 10
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值