(Java多线程系列一)快速入门

Java多线程快速入门

1、线程和进程的区别

> 进程是所有线程的集合,每一个线程是进程的一条执行路径。

2、多线程的应用场景

> 多线程主要体现在提高程序的效率,比如迅雷多线程下载,多线程分批发送短信等。

3、多线程的创建方式

(1)继承Thread类,重写run()方法
class ThreadDemo extends Thread {
    @Override
    public void run() {
        System.out.println("这里是子线程");
        System.out.println("线程名称:" + this.getName());
        System.out.println("线程ID:" + this.getId());
    }
}

public class JavaThreadDemo01 {

    public static void main(String[] args) {
        System.out.println("这里是主线程");
        ThreadDemo threadDemo = new ThreadDemo();
        threadDemo.start();
    }
}
(2)实现Runnable接口,重写run()方法
class RunnableDemo implements Runnable {

    @Override
    public void run() {
        System.out.println("这里是子线程");
        System.out.println("线程名称:" + Thread.currentThread().getName());
        System.out.println("线程ID:" + Thread.currentThread().getId());
    }
}

public class JavaThreadDemo02 {

    public static void main(String[] args) {
        System.out.println("这里是主线程");
        RunnableDemo runnableDemo = new RunnableDemo();
        Thread thread = new Thread(runnableDemo);
        thread.start();
    }
}
(3)使用匿名内部类方式
public class JavaThreadDemo03 {

    public static void main(String[] args) {
        System.out.println("主线程");
        // 使用实现接口的方式
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("这里是子线程");
                System.out.println("线程名称:" + Thread.currentThread().getName());
                System.out.println("线程ID:" + Thread.currentThread().getId());
            }
        });
        thread1.start();

        // 使用lambda表达式
        Thread thread2 = new Thread(() -> {
            System.out.println("这里是子线程");
            System.out.println("线程名称:" + Thread.currentThread().getName());
            System.out.println("线程ID:" + Thread.currentThread().getId());
        });
        thread2.start();
    }
}
(4)使用继承Thread类还是使用实现Runnable接口的方式新建线程好?

> 使用实现Runnable接口的方式好,因为java是单继承,所以继承Thread接口后不能继承其他父类,而实现Runnable接口后还可以实现其他接口,继承其他父类。

(5)启动线程调用start()方法还是run()方法?

> 调用run()方法是使用实例调用,是单线程调用,不会开启多线程。

4、多线程运行状态

> ①新建状态(NEW):新建一个线程,线程还没有开始运行,此时线程就是新建状态

> ②就绪状态:当线程对象调用了start()方法即启动了线程,start()方法创建线程运行的系统资源,并调度线程运行run()方法。当start()方法返回后,线程就处于就绪状态。处于就绪状态的线程并不一定立即运行run()方法,线程还必须同其他线程竞争cpu时间,只有获得cpu时间才能运行线程。因为在单cpu的计算机系统中,不可能同时运行多个线程,一个时刻仅能有一个线程处于运行状态,因此可能存在多个处于就绪状态的线程,对于多个就绪状态的线程是由Java运行时系统的线程调度程序来调度的。

> ③运行状态(RUNNABLE):当线程获取cpu时间后,线程进入运行状态,真正开始执行run()方法。

> ④阻塞状态(BLOCKED/WAITING/TIMED_WAITING):a、线程通过调用sleep()方法进入睡眠;b、线程调用一个在I\O上被阻塞的操作;c、线程试图得到一个锁,而该锁正被其他线程持有;d、线程在等待某个触发条件。
> BLOCKED:等待监视器锁,实际上就是被synchronized方法或块阻塞
>
> WAITING:等待用notify()或者notifyAll()唤醒
>
> TIMED_WAITING:等待用notify()或者notifyAll()唤醒,如果没有等到,时间到了也会退出这一状态

> ⑤死亡状态(TERMINATED):a、run()方法正常退出自然死亡;b、一个未捕获的异常终止了run()方法使线程猝死。

5、判断线程的存活状态

> ①调用isAlive()方法,如果是可运行或被阻塞,方法返回true。

> ②线程是新建状态或线程死亡,返回false。

源码地址

声明:该文章系转载,转载该文章的目的在于更广泛的传递信息,并不代表本网站赞同其观点,文章内容仅供参考。

本站是一个个人学习和交流平台,网站上部分文章为网站管理员和网友从相关媒体转载而来,并不用于任何商业目的,内容为作者个人观点, 并不代表本网站赞同其观点和对其真实性负责。

我们已经尽可能的对作者和来源进行了通告,但是可能由于能力有限或疏忽,导致作者和来源有误,亦可能您并不期望您的作品在我们的网站上发布。我们为这些问题向您致歉,如果您在我站上发现此类问题,请及时联系我们,我们将根据您的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。