Java多线程(一)——多线程实现方法和生命周期

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xcymorningsun/article/details/87929272

目录

一、引言

二、多进程与多线程

三、实现方法

1、继承Thread接口

2、实现runnable接口,传入Thread运行

3、注意

四、生命周期

五、总结


一、引言

       之前多线程了解的基本是皮毛,后来是因为对javaweb中tomcat接受请求,用户并发访问如何使用多线程不太清楚,所以又重新把多线程拾了起来,发现了一片新大陆。

        好多地方用到了多线程,使用同步以保证数据安全:collection中vector与arraylist线程安全,数据库中的读写锁互斥,消息队列中take与put的安全性,tomcat服务访问等等。

列了个大纲,写了下这一些列博客的内容梳理

二、多进程与多线程

        一个进程对应一个应用程序。例如:在 windows 操作系统启动 Word 就表示启动了一个 进程。在 java 的开发环境下启动 JVM,就表示启动了一个进程。多进程的作用不是提高执行速度,而是提高 CPU 的使用率。 

        线程是一个进程中的执行场景,一个进程可以启动多个线程,线程之间共享java堆和方法区,不共享java栈。多线程不是为了提高执行速度,而是提高应用程序的使用率。 
 

三、实现方法

首先介绍实现方法,这个是最直观的认识

1、继承Thread接口

public class Test {
    public  static  void main(String [] args){

        MyThread myThread=new MyThread();
        myThread.start();
    }
}
class MyThread extends Thread
{
    @Override
    public void run() {
        while(true)
        {
            try {
                Thread.sleep(1000);//该线程休息1秒钟
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程——"+ Thread.currentThread().getName());
        }
    }
}

2、实现runnable接口,传入Thread运行

package com.thread;

public class Test {
    public  static  void main(String [] args){

        new Thread(new Runnable() {
            public void run() {
                while(true)
                {
                    try {
                        Thread.sleep(1000);//该线程休息1秒钟
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("线程——"+ Thread.currentThread().getName());
                }
            }
        }).start();

    }
}

这个是匿名内部类的形式把Runnable对象传入Thread的构造函数当中。

3、注意

其实还有callable方法,可以返回值以后再慢慢讲。这里我们必须调用Thread的start()方法,这样才能通过jvm开启一个多线程,直接调用Thread的run()方法只是调用一个简单点的函数。

还有个比较经典的问题,下面的程序输出什么(即在runnable中实现run方法,又在Thread中实现run方法,多线程会调用哪一个)

public class Test {
    public  static  void main(String [] args){

        new Thread(new Runnable() {
            public void run() {
                while(true)
                {
                    try {
                        Thread.sleep(1000);//该线程休息1秒钟
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("线程111——"+ Thread.currentThread().getName());
                }
            }
        }){
            public void run() {
                while(true)
                {
                    try {
                        Thread.sleep(1000);//该线程休息1秒钟
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("线程222——"+ Thread.currentThread().getName());
                }
            }
        }.start();

    }
}

答案是Thread中的run方法,因为Thread类中run方法如下,target是传入的runnable对象,如果传入了runnable对象,就会执行runnable的run方法,但是现在Thread类中的run方法被继承,父类的run方法失效自然就不执行target.run方法,只会执行我们写好的继承类中的run方法。

    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

四、生命周期

一个线程和vue、activity、servlet一样也有自己生命周期,了解生命周期可以使我们更好的理解多线程。

新建状态:使用关键字new创建线程后,线程处于等待状态,等待start;

就绪状态:线程执行start,线程排入就绪队列,等待jvm调度器调度;

运行状态:当线程抢到cpu资源,执行run方法,这时可以进入阻塞、就绪、和死亡任意一个状态;

死亡状态:线程完成任务或者stop/interrupt,线程结束进入死亡状态;

阻塞状态:如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:

  • 等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。

  • 同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。

  • 其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。

五、总结

  • 多进程与多线程
  • 实现方法
  • 生命周期

猜你喜欢

转载自blog.csdn.net/xcymorningsun/article/details/87929272