Java 多线程 实现方式 线程的生命周期

目录

1. 线程的实现方式

1.1 实现 Runnable 接口,重写 run 方法,无返回值

1.2 实现 Callable 接口,重新 call 方法,有返回值

1.3 继承 Thread 类,重写 run 方法,无返回值

2. 线程的生命周期

2.1 线程状态:new

2.2 线程状态:runnable

2.3 线程状态:blocked

2.4 线程状态:waiting

2.5 线程状态:timed waiting

2.6 线程状态:terminated

3. 总结

 

每一段代码,都是可以单独执行的,可以放到本地,查看一下执行效果。

千篇一律的看,不如自己动手实践一下,让咱们靠着理解,去加深记忆。


1. 线程的实现方式

线程的的实现方式分为三种。

1.1 实现 Runnable 接口,重写 run 方法,无返回值

1.2 实现 Callable 接口,重新 call 方法,有返回值

1.3 继承 Thread 类,重写 run 方法,无返回值

前两种是创建了一个可执行任务,直接调用 run 方法、call 方法,并不是以多线程的方式进行执行的。只有通过 Thread 类的 star 方法,启动的,才是以多线程的方式进行执行的。

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

public class ThreadTest {
    public static void main(String[] args) throws Exception {

        long start = System.currentTimeMillis();
        System.out.println("主线程 开始");

        System.out.println("1. Runnable 测试代码");
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("Runnable " + Thread.currentThread().getName() + ":runing...");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Runnable " + Thread.currentThread().getName() + ":over...");
            }
        };
        new Thread(runnable).start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("");
        System.out.println("2. Callable 测试代码");
        Callable<String> callable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                System.out.println("Callable " + Thread.currentThread().getName() + ":runing...");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Callable " + Thread.currentThread().getName() + ":返回值,娃哈哈...");
                return "娃哈哈";
            }
        };
        FutureTask<String> futureTask = new FutureTask<>(callable);
        new Thread(futureTask).start();
        System.out.println("callable方式 返回值:" + futureTask.get());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        System.out.println("");
        System.out.println("3. 继承 Thread 重写 run 方法");
        MyThread myThread = new MyThread();
        myThread.start();

        System.out.println("主线程 结束,耗时 " + (System.currentTimeMillis() - start));
    }
}

class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("继承 Thread " + Thread.currentThread().getName() + ":runing...");
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("继承 Thread " + Thread.currentThread().getName() + ":over...");
    }
}
									

2. 线程的生命周期

线程的生命周期可以整体可以涵盖为 4 种流程,分别是,新建、就绪、阻塞、终止。

这 4 种流程对应了 6 种状态。

新建:new

就绪:runnable

阻塞:blocked、waiting、timed waiting

终止:terminated

2.1 线程状态:new

public class ThreadTest {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "线程A");
        System.out.println("[ " + thread.getName() + " ] 的状态是:" + thread.getState());
        //控制台输出: [ 线程A ] 的状态是:NEW
    }
}

2.2 线程状态:runnable

public class ThreadTest {
    public static void main(String[] args) throws Exception {
        // 1. 声明一个线程
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    for (int i = 0; i < 10; i++) {
                        System.out.println(Thread.currentThread().getName() + " runing... " + i);
                    }
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "线程A");

        // 2. 启动线程
        thread.start();

        // 3. 查看线程状态 [ 因为CPU执行顺序是不一定的,此时假设,启动后,执行了,主线程中,查看状态的代码 ]
        System.out.println("[ " + thread.getName() + " ] 的状态是:" + thread.getState());
        // 控制台输出:
        // [ 线程A ] 的状态是:RUNNABLE
        // 线程A runing... 0
        // ......
        // 线程A runing... 9
    }
}

2.3 线程状态:blocked

import sun.misc.Lock;

public class ThreadTest {
    public static void main(String[] args) throws Exception {
        // 1. 生命锁对象
        Lock lock = new Lock();

        // 2. 声明两个线程
        MyThread threadA = new MyThread(lock, "线程A");
        MyThread threadB = new MyThread(lock, "线程B");
        threadA.start();
        threadB.start();
        try {
                Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 3. 查看状态
        System.out.println("[ " + threadA.getName() + " ] 的状态是:" + threadA.getState());
        System.out.println("[ " + threadB.getName() + " ] 的状态是:" + threadB.getState());
    }
}

class MyThread extends Thread {
    private Lock lock = null;

    public MyThread(Lock lock, String name) {
        this.lock = lock;
        super.setName(name);
    }
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + ":runing...");
        try {
            System.out.println(Thread.currentThread().getName() + ":runing...开始争夺锁");
            synchronized (lock) {
                System.out.println(Thread.currentThread().getName() + ":runing...拿到了锁");
                System.out.println(Thread.currentThread().getName() + ":runing...模拟业务执行...");
                Thread.sleep(1000);
            }
            System.out.println(Thread.currentThread().getName() + ":over...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}
									

2.4 线程状态:waiting

import sun.misc.Lock;

public class ThreadTest {
    public static void main(String[] args) throws Exception {
        // 1. 生命锁对象
        Lock lock = new Lock();

        // 2. 声明两个线程
        MyThread threadA = new MyThread(lock, "线程A");
        MyThread threadB = new MyThread(lock, "线程B");
        threadA.start();
        threadB.start();
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 3. 第一次查看状态
        System.out.println("[ " + threadA.getName() + " ] 的状态是:" + threadA.getState());
        System.out.println("[ " + threadB.getName() + " ] 的状态是:" + threadB.getState());


        try {
            Thread.sleep(3000);
            synchronized (lock) {
                lock.notifyAll();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 4. 第二次查看状态
        System.out.println("[ " + threadA.getName() + " ] 的状态是:" + threadA.getState());
        System.out.println("[ " + threadB.getName() + " ] 的状态是:" + threadB.getState());
    }
}

class MyThread extends Thread {
    private Lock lock = null;

    public MyThread(Lock lock, String name) {
        this.lock = lock;
        super.setName(name);
    }
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + ":runing...");
        try {
            System.out.println(Thread.currentThread().getName() + ":runing...开始争夺锁");
            synchronized (lock) {
                System.out.println(Thread.currentThread().getName() + ":runing...拿到了锁");
                System.out.println(Thread.currentThread().getName() + ":runing...模拟业务执行...");
                lock.wait();
                System.out.println(Thread.currentThread().getName() + ":runing...模拟业务执行...2");
            }
            System.out.println(Thread.currentThread().getName() + ":over...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}
									

2.5 线程状态:timed waiting



public class ThreadTest {
    public static void main(String[] args) throws Exception {
        // 1. 声明线程
        MyThread threadA = new MyThread();
        threadA.setName("线程A");
        threadA.start();
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 2. 查看状态
        System.out.println("[ " + threadA.getName() + " ] 的状态是:" + threadA.getState());

        // 控制台输出
        // 线程A:runing...
        // [ 线程A ] 的状态是:TIMED_WAITING
        // 线程A:over...
    }
}

class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + ":runing...");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + ":over...");
    }
}
									

2.6 线程状态:terminated



public class ThreadTest {
    public static void main(String[] args) throws Exception {

        // 1. 声明两个线程
        MyThread threadA = new MyThread();
        threadA.start();
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 3. 第一次查看状态
        System.out.println("[ " + threadA.getName() + " ] 的状态是:" + threadA.getState());
    }
}

class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + ":runing...");
        System.out.println(Thread.currentThread().getName() + ":runing...开始争夺锁");
        System.out.println(Thread.currentThread().getName() + ":runing...拿到了锁");
        System.out.println(Thread.currentThread().getName() + ":runing...模拟业务执行...");
        System.out.println(Thread.currentThread().getName() + ":runing...模拟业务执行...2");
        System.out.println(Thread.currentThread().getName() + ":over...");
    }
}
									

3. 总结

线程的生命周期分为四种, 新建、就绪、阻塞、终止,对应六种状态,

       新建:new,

       就绪:runnable,

       阻塞:blocked、waiting、timed waiting,

       终止:terminated。

当线程被创建出来以后,对应的是new,随后通过start()方法启动对应runnable,cpu切片时间执行完成,但是业务没有走完,线程回归到runable状态,当在cpu切片时间内执行完毕,线程进入terminated 终止状态,线程生命周期结束。
在线程执行过程中,调用sleep、wait 传入时间,随后线程进入阻塞状态中的 timed waiting 定时等待状态,待指定时间过后,线程进入runnable 就绪状态,等待cpu调用。
在线程执行过程中,调用 wait 方法,不传入时间、线程进入到 waiting 等地状态,待外部调用 notify 或 notifyAll 方法通知线程进入到 runable 就绪状态。
在A线程执行过程中,调用B线程的 join 方法后,在B线程执行完毕之前,A线程进入到 waiting 等地状态,等待B线程执行完毕后,自动通知A线程进入到 runable 就绪状态。
线程A、线程B,在争夺锁的过程,假如A先拿到锁,B就会进入到blocked,阻塞状态,等待A释放锁后,自己再去拿锁。

 

致谢

https://zhuanlan.zhihu.com/p/58966050
https://www.bilibili.com/video/BV1k74118721?t=513&p=24
https://blog.csdn.net/maoshaomiao/article/details/90756576

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值