线程详解创建及生命周期

线程详解创建及生命周期,第1张

线程详解
  • 前言
  • 线程的生命周期
  • 线程的创建
    • 继承Thread类
    • 实现Runnable接口
  • Thread 和 Runnable 的区别

前言

线程是 *** 作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速。比如,如果一个线程完成一个任务要100毫秒,那么用十个线程完成该任务只需10毫秒。为了更好的理解线程知识我特地做了一下分享

线程的生命周期

生命周期的五种状态

  1. 新建(new Thread)

当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。 例如:Thread t1=new Thread();

  1. 就绪(runnable)

线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。例如:t1.start();

  1. 运行(running)

线程获得CPU资源正在执行任务(run()方法),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。

  1. 堵塞(blocked)

(1)等待阻塞 ( o.wait-> 等待对列 )

运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue) 中。

(2)同步阻塞 (lock-> 锁池 )

运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线 程放入锁池(lock pool)中。

(3)其他阻塞 (sleep/join)

运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,
JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O
处理完毕时,线程重新转入可运行(runnable)状态。

  1. 死亡(dead)

线程会以下面三种方式结束,结束后就是死亡状态。

(1)正常结束: run()或call()方法执行完成,线程正常结束。
(2)异常结束: 线程抛出一个未捕获的Exception或Error。 调用
(3)stop: 直接调用该线程的stop()方法来结束该线程— 该方法通常容易导致死锁,不推荐使用。

线程的创建

继承Thread类
  • Thread类是所有线程类的父类,实现了对线程的抽取和封装
    具体实现见代码如下
public class ThreadTest {
    public static void main(String[] args) throws InterruptedException {
        // 计时器
        Long start = System.currentTimeMillis();
        Random random = new Random();
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 100000; i++) {
            // 1、 造一个线程
            Thread thread = new Thread() {
                @Override
                public void run() {
                    list.add(random.nextInt());
                }

            };
            // 启动线程
            thread.start();
            // 其目的是等待当前线程执行完毕后,”计算单元”与主线程汇合。即主线程与子线程汇合之意。

            /*main是主线程,在main中创建了thread线程,在main中调用了thread.join(),那么等thread结束后再执行main代码。

            在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,

            主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后,

            需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到join()方法了。

            “等待该线程终止。”
            */

            thread.join();

        }
        System.out.println("时间" + (System.currentTimeMillis() - start));
        System.out.println("大小" + list.size());
    }
}

多线程实现卖票

// 创建线程  extends Thread
class Station extends Thread {

    // 通过构造方法给线程名字赋值
    public Station(String name) {
        super(name);// 给线程名字赋值
    }

    // 为了保持票数的一致,票数要静态
    static int tick = 20;

    // 创建一个静态钥匙
    static Object ob = "aa";//值是任意的

    // 重写run方法,实现买票 *** 作
    @Override
    public void run() {
        while (tick > 0) {
            synchronized (ob) {// 这个很重要,必须使用一个锁,
                // 进去的人会把钥匙拿在手上,出来后才把钥匙拿让出来
                if (tick > 0) {
                    System.out.println(getName() + "卖出了第" + tick + "张票");
                    tick--;
                } else {
                    System.out.println("票卖完了");
                }
            }
            try {
                sleep(1000);//休息一秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }

}

// 创建调用方法
class MainClass {
    /**
     * java多线程同步锁的使用
     * 示例:三个售票窗口同时出售10张票
     */
    public static void main(String[] args) {
        //实例化站台对象,并为每一个站台取名字
        Station station1 = new Station("窗口1");
        Station station2 = new Station("窗口2");
        Station station3 = new Station("窗口3");

        // 让每一个站台对象各自开始工作
        station1.start();
        station2.start();
        station3.start();

    }

}
  • join是什么

         其目的是等待当前线程执行完毕后,”计算单元”与主线程汇合。即主线程与子线程汇合之意。
         
         main是主线程,在main中创建了thread线程,在main中调用了thread.join(),那么等thread结束后再执行main代码。
    
          在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,
    
          主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后,
    
          需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到join()方法了。
    
          “等待该线程终止。”
    
实现Runnable接口

代码实现如下到
多线程卖票

// 创建线程
class Runnable1 {

    // 为了保持票数的一致,票数要静态
    static int tick = 20;

    // 创建一个静态钥匙
    static Object ob = "aa";//值是任意的
    static Runnable runnable = new Runnable() {
        @Override
        public void run() {
            while (tick > 0) {
                synchronized (ob) {// 这个很重要,必须使用一个锁,
                    // 进去的人会把钥匙拿在手上,出来后才把钥匙拿让出来
                    if (tick > 0) {
                        System.out.println(tick-- + "卖出了第" + tick + "张票");
                        tick--;
                    } else {
                        System.out.println("票卖完了");
                    }
                }
                try {
                    sleep(1000);//休息一秒
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };
    public static void main(String[] args) {
        Thread t1 = new Thread(runnable);
        Thread t2 = new Thread(runnable);
        Thread t3 = new Thread(runnable);
        t1.start();
        t2.start();
        t3.start();
    }

}

Thread 和 Runnable 的区别

Thread和Runnable的实质是继承关系,没有可比性。无论使用Runnable还是Thread,都会new Thread,然后执行run方法。用法上,如果有复杂的线程 *** 作需求,那就选择继承Thread,如果只是简单的执行一个任务,那就实现runnable。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/730360.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-27
下一篇 2022-04-27

发表评论

登录后才能评论

评论列表(0条)

保存