zoukankan      html  css  js  c++  java
  • Java线程类

    基础知识

    线程状态

    根据Thread.State类中的描述,Java中线程有六种状态:NEW,RUNNABLE,WAITING,TERMINATED,BLOCKED。

    就绪状态(NEW):当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。

    运行状态(RUNNABLE):如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。

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

    • 等待阻塞(WAITING):运行状态中的线程执行 wait() ,join(),park()方法,使线程进入到等待阻塞状态。
    • 同步阻塞(BLOCKED):线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。
    • 其他阻塞(TiMED_WAITHIN):通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入运行态。

    死亡状态(TERMINATED):一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。

    值得注意的是,以上状态为JVM线程状态,不反应操作系统线程状态。

                                                线程状态迁移图

    线程优先级

    每一个 Java 线程都有一个优先级,这样有助于操作系统确定线程的调度顺序。线程优先级是一个正整数,所有创建的线程默认优先级为5(Thread.NORM_PRIORITY),可设置最大优先级为10(Thread.MAX_PRIORITY),最小优先级为1(Thread.MIN_PRIORITY)。在所有得到其他资源并等待处理器资源的线程中,优先级高的线程理论上将被更有可能被优先调度。

    守护线程

    守护线程意味着不重要的线程(骑士对于公主来说,是守护者,是可有可无的备胎),因而当某进程只有守护线程在执行时,该进程会立即结束运行。    

    创建可运行的类

    继承Thread类

    1.新建类继承Thread类。

    2.重写run()方法。该run()方法的方法体就代表了线程需要完成的任务。 

    3.创建Thread子类的实例。

    4.调用线程对象的start()方法来启动该线程。

    public class myThread {
        public static void main(String[] args){
            Thread t = new newThread();
            t.start();
        }
    }
    
    class newThread extends Thread{
        @Override
        public void run() {
            System.out.println(this.getName()+":start!");
        }
    }

    实现Runnable接口

    1.新建类实现Runnable接口。

    2.重写run方法。该run()方法的方法体就代表了线程需要完成的任务。

    3.创建新建类的实例target。

    4.以target作为参数创建Thread的实例。

    5.调用线程对象的start()方法来启动该线程。

    public class myThread {
        public static void main(String[] args){
            newThread nt = new newThread();
            Thread t = new Thread(nt);
            t.start();
        }
    }
    
    class newThread implements Runnable{
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName()+":start!");
        }
    }

    两种方法的优点

    1.继承Thread这种方法方便易用,更容易获取当前线程对象。

    2.实现Runnable接口这种方法可以继承其他父类;多个线程可以共享一个target对象,适合多个相同线程来处理同一份资源的情况。

    可否直接调用run()方法开启线程

    事实上,线程对象只有调用start()方法才能在新的线程中运行run()方法体中的代码,而直接调用run()方法意味着在当前线程中调用run()方法,即run()方法被当作普通方法处理了,并不会创建新线程

    public class myThread {
        public static void main(String[] args){
            newThread nt = new newThread();
            Thread t = new Thread(nt,"myThread");
            t.run();
        }
    }
    
    class newThread implements Runnable{
        @Override
        public void run() {
            System.out.println("Name:"+Thread.currentThread().getName());
        }
    }
    //结果
    Name:main

    常用API

    构造器

    Thread() ,Thread(String name)   //可以传入一个字符串或什么也不传入,就是创建一个什么任务也不做的线程

    Thread(Runnable target)

    Thread(Runnable target,String name)    //传入一个可运行的对象,name作为线程名称

    获取线程信息

    static Thread currentThread()      //获取当前线程对象

    long getID()            //获取线程标识

    String getName()     //获取线程名称

    int getPriority()     //获取线程优先级

    Thread.state getState()     //获取线程状态

    public class myThread {
        public static void main(String[] args){
            newThread nt = new newThread();
            Thread t = new Thread(nt,"myThread");
            t.start();
            newThread.getInformation(Thread.currentThread());
            newThread.getInformation(t);
        }
    }
    
    class newThread implements Runnable{
        @Override
        public void run() {
        }
    
        static void getInformation(Thread t){
            System.out.println("name:"+t.getName());
            System.out.println("id:"+t.getId());
            System.out.println("priority:"+t.getPriority());
            System.out.println("state:"+t.getState());
        }
    }
    
    //结果
    name:main
    id:1
    priority:5
    state:RUNNABLE
    name:myThread
    id:13
    priority:5
    state:TERMINATED

    设置线程信息

    void setName()    //设置线程名称

    void setPriority()    //设置线程优先级

    void setDaemon(Boolean on)   //设置为守护线程,只有当线程调用start()方法之前才可调用

    判断线程状态

    boolean isAlive()        //判断线程是否死亡,

    boolean isDaemon()      //判断线程是否为守护线程

    boolean isInterrupted()     //判断线程是否中断,并且将其变为非中断状态

    public class myThread {
        public static void main(String[] args){
            newThread nt = new newThread();
            Thread t = new Thread(nt,"myThread");
            System.out.println("未调用start()时:"+t.isAlive());
            t.setDaemon(true);
            t.start();
            newThread.getInformation(t);
            newThread.getInformation(Thread.currentThread());
        }
    }
    
    class newThread implements Runnable{
        @Override
        public void run() {
        }
    
        static void getInformation(Thread t){
            System.out.println(t.getName()+"-isAlive:"+t.isAlive());
            System.out.println(t.getName()+"-isDaemon:"+t.isDaemon());
            System.out.println(t.getName()+"-isInterrupted:"+t.isInterrupted());
    
        }
    }
    
    //结果
    未调用start()时:false
    myThread-isAlive:true
    myThread-isDaemon:true
    myThread-isInterrupted:false
    main-isAlive:true
    main-isDaemon:false
    main-isInterrupted:false

    sleep()方法

    该方法让当前线程暂停执行一段时间。

    static void sleep(long millis)          //暂停millis毫秒

    static void sleep(long millis,long nanos)    //暂停millis毫秒+nanos纳秒

    join()方法

    join意味加入,可以抽象地认为它是加入当前线程队伍,也就是说,发生t.join()调用时调用方t加入当前线程队伍,当前线程需要等待t线程执行完毕后才开始执行

    public class myThread {
        public static void main(String[] args)throws InterruptedException {
            newThread nt = new newThread();
            Thread t = new Thread(nt,"subThread");
            t.start();
            t.join();
            for (int i = 1; i <= 1000; i++) {
                if (i%500==0) {
                    System.out.println("mainThread finish!");
                }
            }
    
        }
    }
    
    class newThread implements Runnable{
        @Override
        public void run(){
            for (int i = 1; i <= 1000; i++) {
                try {
                    Thread.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (i%500==0)
                    System.out.println("subThread finish!");
            }
        }
    }

    结果如下,主线程显然是比子线程执行时间更短,然而还是主线程最后执行完

    subThread finish!
    subThread finish!
    mainThread finish!
    mainThread finish!

    方法还有另外两个重载形式

    void join(long millis)          //等待millis毫秒

    void join(long millis,long nanos)    //等待millis毫秒+nanos纳秒

    join()内部使用wait()方法和notifyall()方法来实现的,因而它与sleep()方法的区别是,sleep方法不会释放持有的锁,而join()方法会释放持有的锁。

    //将t.join()改为t.join(50,50)后,结果不同:
    mainThread finish!
    mainThread finish!
    subThread finish!
    subThread finish!

    yield()方法

    让出当前线程cup的使用权,此时就绪队列中高优先级 的线程将被执行,此外该方法不释放线程持有的锁。

  • 相关阅读:
    html5 canvas 小例子 旋转的时钟
    用深度学习(CNN RNN Attention)解决大规模文本分类问题
    生成式对抗网络GAN 的研究进展与展望
    linux 系统信息查看
    cmd 更改字体
    查看sbt版本
    机器学习算法汇总
    spark 大数据 LR测试
    spark
    hadoop生态圈介绍
  • 原文地址:https://www.cnblogs.com/lht-record/p/11316088.html
Copyright © 2011-2022 走看看