资讯专栏INFORMATION COLUMN

Java基础之线程Thread

tomlingtm / 1289人阅读

摘要:在程序开发中一定遇到并发编程的场景虽然我们大部分时间并不直接使用但是是多线程的基础面试中也会总是被问到与线程有关的问题那么线程都有哪些知识呢最近在研究线程的源码的时候也总结了关于线程一些基本知识线程是什么线程是轻量级的进程是操作系统调度任务

在程序开发中, 一定遇到并发编程的场景, 虽然我们大部分时间并不直接使用Thread, 但是Thread是多线程的基础, 面试中也会总是被问到与线程有关的问题; 那么线程都有哪些知识呢? 最近在研究线程的源码的时候也总结了关于线程一些基本知识;
线程是什么

线程是轻量级的进程, 是操作系统调度任务到CPU的最小单元;

多线程编程的优点

1、多线程编程能够最大程度的利用多核设备上面的CPU资源, 保证任务处理的足够快, 及时响应客户端的额请求

2、线程的创建的代价比创建进程的代价小很多, 同时多线程的上下文切换也更快; 《操作系统概念 第六版》 在Solaris 2上面, 创建进程比创建线程慢30倍, 而进程的上下文切换比线程的上下文切换慢5倍;

Java中线程的状态有哪些

查看java.lang.Thread的源码有如下代码:

public enum State {
    /**
     * Thread state for a thread which has not yet started.
     */
    NEW,

    /**
     * Thread state for a runnable thread.  A thread in the runnable
     * state is executing in the Java virtual machine but it may
     * be waiting for other resources from the operating system
     * such as processor.
     */
    RUNNABLE,

    /**
     * Thread state for a thread blocked waiting for a monitor lock.
     * A thread in the blocked state is waiting for a monitor lock
     * to enter a synchronized block/method or
     * reenter a synchronized block/method after calling
     * {@link Object#wait() Object.wait}.
     */
    BLOCKED,

    /**
     * Thread state for a waiting thread.
     * A thread is in the waiting state due to calling one of the
     * following methods:
     * 
    *
  • {@link Object#wait() Object.wait} with no timeout
  • *
  • {@link #join() Thread.join} with no timeout
  • *
  • {@link LockSupport#park() LockSupport.park}
  • *
* *

A thread in the waiting state is waiting for another thread to * perform a particular action. * * For example, a thread that has called Object.wait() * on an object is waiting for another thread to call * Object.notify() or Object.notifyAll() on * that object. A thread that has called Thread.join() * is waiting for a specified thread to terminate. */ WAITING, /** * Thread state for a waiting thread with a specified waiting time. * A thread is in the timed waiting state due to calling one of * the following methods with a specified positive waiting time: *

    *
  • {@link #sleep Thread.sleep}
  • *
  • {@link Object#wait(long) Object.wait} with timeout
  • *
  • {@link #join(long) Thread.join} with timeout
  • *
  • {@link LockSupport#parkNanos LockSupport.parkNanos}
  • *
  • {@link LockSupport#parkUntil LockSupport.parkUntil}
  • *
*/ TIMED_WAITING, /** * Thread state for a terminated thread. * The thread has completed execution. */ TERMINATED; }

1、NEW: 线程还没有启动的时候, 状态就是NEW 即 新建状态

2、RUNNABLE: 当一个线程处于运行中或者等待CPU调度的时候, 状态就是 RUNNABLE状态; 有些地方也称为 就绪状态

3、BLOCKED: 当一个线程在等待别的线程释放锁资源的时候, 状态就是BLOCKED, 或者在该线程获取到锁之后, 在同步代码块里面调用了Wait方法, 这时候释放锁, 在获取到其他线程的notify或者notifyAll通知之后, 重新进入 同步代码块这段时间 该线程也是BLOCKED状态的;

4、WAITING: 当正在运行的线程调用了Object.wait()方法 或者 Thread.join()方法 或者 LockSupport.park()方法之后, 会进入到WAITING状态

5、TIMED_WAITING: 当正在运行的线程调用Object.wait(n) 或者 Thread.join(n) 或者 LockSupport.parkUntil(blocker, n) 会进入到 TIMED_WAITING 状态

6、TERMINATED: 当线程结束后, 会进入到 TERMINATED 状态.

状态转换如下, 该图中比Java的状态多了一个RUNNING状态, 来区别 线程的就绪状态 与 运行状态 更加方便读者理解;

线程状态转换 线程状态转换之NEW

下面来看一下线程的状态转换用Java怎么实现:

如上面所述: 刚刚创建的线程处于NEW状态, 那么我们可以通过如下代码打印其状态:

    Thread thread = new Thread(new Runnable() {
       public void run() {
       }
    });
    System.out.println(thread.getState());
线程状态转换之RUNNABLE

那么线程如何进入到RUNNABLE状态呢? 调用Threadstart方法即可; 我们在Runnable的实现里面增加对于当前线程状态的打印即可:

    public static void main(String[] args) {
       Thread thread = new Thread(new Runnable() {
           public void run() {
                System.out.println("线程进入:" + Thread.currentThread().getState());
           }
       });

       System.out.println(thread.getState());
       thread.start();
    }
线程状态转换之TIMED_WAITING

那么线程怎么进入到TIMED_WAITING状态呢? 通过调用 sleep(n) join(n) 或者 wait(n)都可以进入到TIMED_WAITING状态:

调用Thread.sleep()

public static void main(String[] args) {
    Thread thread = new Thread(new Runnable() {
        public void run() {
            System.out.println("线程进入:" + Thread.currentThread().getState());
            try {
                Thread.sleep(1000 * 60);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });

    System.out.println(thread.getState());
    thread.start();
}

调用obj.wait(time)

public static void main(String[] args) {
    Thread thread = new Thread(new Runnable() {
        public void run() {
            synchronized (Client.class) {
                System.out.println("线程进入:" + Thread.currentThread().getState());
                try {
                    Client.class.wait(60 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    });

    System.out.println(thread.getState());
    thread.start();
}

上图中表示: 在Client.class上面等待; 等待其他对象调用Client.class.notify()方法或者等待时间到期.

调用thread.join(time)

public static void main(String[] args) {
    final Thread thread = new Thread(new Runnable() {
        public void run() {
            synchronized (Client.class) {
                System.out.println("线程进入:" + Thread.currentThread().getState());
                try {
                    Client.class.wait(60 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Client.class对象上等待超时");
            }
        }
    });

    System.out.println(thread.getState());
    thread.start();

    Thread thread2 = new Thread(new Runnable() {
        public void run() {
            synchronized (Client.class) {
                try {
                    thread.join(50 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Thread1结束");
            }
        }
    });

    thread2.start();
}

表示 第二个线程在等待第一个线程执行完成或者超时;

线程状态转换之WAITING

如果想要一个线程进入到WAITING状态, 那么只需要跟上面步骤一样, Thread.sleep()除外, 但是调用的时候不要传超时时间即可;

public static void main(String[] args) {
    final Thread thread = new Thread(new Runnable() {
        public void run() {
            synchronized (Client.class) {
                System.out.println("线程进入:" + Thread.currentThread().getState());
                try {
                    Client.class.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("被其他线程调用Client.class.notify()唤醒");
            }
        }
    });

    System.out.println(thread.getState());
    thread.start();

    Thread thread2 = new Thread(new Runnable() {
        public void run() {
            synchronized (Client.class) {
                try {
                    thread.join(50 * 1000);
                    Client.class.notify();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Thread1结束");
            }
        }
    });

    thread2.start();
}

只要是没有时间的等待都会处于WAITING状态, 比如把上面代码修改一下, 换成join()也可以让线程处于 WAITING状态:

public static void main(String[] args) {
    final Thread thread = new Thread(new Runnable() {
        public void run() {
            synchronized (Client.class) {
                System.out.println("线程进入:" + Thread.currentThread().getState());
                try {
                    Client.class.wait(50 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("被其他线程调用Client.class.notify()唤醒");
            }
        }
    });

    System.out.println(thread.getState());
    thread.start();

    Thread thread2 = new Thread(new Runnable() {
        public void run() {
            synchronized (Client.class) {
                try {
                    System.out.println("即将进入等待线程1完成的状态");
                    thread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Thread1结束");
            }
        }
    });

    thread2.start();
}

如上代码表示线程2会在线程1执行结束之后再结束, 所以线程2就会进入到WATIING状态

线程状态转换之BLOCKED

上面已经看到, 通过调用线程的函数就可以控制线程的状态, 那么如何进入到BLOCKED状态呢?进入到BLOCKED状态, 按照上面的转换图 可以翻译为 多个线程出现竟态的时候, 其他线程会进入BLOCKED状态, 只有一个线程会在RUNNABLE状态,比如如下代码:

public static void main(String[] args) {
    final Thread thread = new Thread(new Runnable() {
        public void run() {
            synchronized (Client.class) {
                System.out.println("线程进入:" + Thread.currentThread().getState());
                try {
                    Thread.sleep(1000 * 50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    });

    System.out.println(thread.getState());
    thread.start();

    Thread thread2 = new Thread(new Runnable() {
        public void run() {
            synchronized (Client.class) {
                try {
                    System.out.println("即将进入等待线程1完成的状态");
                    thread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Thread1结束");
            }
        }
    });

    thread2.start();
}

当然, 对于A线程调用了Object.class.wait()方法释放锁之后, 最后被其他线程调用Object.class.notify() A线程再次进入RUNNABLE之前的状态就是 BLOCKED;

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/73607.html

相关文章

  • java并发Thread和Runnable

    摘要:开发中不可避免用到多线程情况,比如中常见的都是运用到多线程,多线程的根本目的是为了更快的执行。其他常用到的多线程比如设计到大量操作用多线程可明显提升效率。中最基础的并发类就是是一个接口,只要实现实现,重写方法就可以实现多线程操作。 java开发中不可避免用到多线程情况,比如web中常见的Servlet、Struts2都是运用到多线程,多线程的根本目的是为了更快的执行。其他常用到的多线程...

    darkbug 评论0 收藏0
  • java高并发从零到放弃(二)

    摘要:可以用代替可以用代替定义的对象的值是不可变的今天就先到这里,大家可以看看这些内容的拓展记得点关注看更新,谢谢阅读 前言 java高并发第二篇讲的是java线程的基础依旧不多说废话 线程和进程 进程是操作系统运行的基础,是一个程序运行的实体,windows上打开任务管理器就能看到进程线程是轻量级的进程,是程序执行的最小单位,是在进程这个容器下进行的 线程基本操作 新建一个线程类有两种方式...

    cloud 评论0 收藏0
  • Java基础进阶ThreadLocal详解

    摘要:基本在项目开发中基本不会用到但是面试官是比较喜欢问这类问题的所以还是有必要了解一下该类的功能与原理的是什么是一个将在多线程中为每一个线程创建单独的变量副本的类当使用来维护变量时会为每个线程创建单独的变量副本避免因多线程操作共享变量而导致的数 ThreadLocal基本在项目开发中基本不会用到, 但是面试官是比较喜欢问这类问题的;所以还是有必要了解一下该类的功能与原理的. Thread...

    worldligang 评论0 收藏0
  • Java基础学习——多线程线程间通信(安全问题、等待唤醒机制)

    摘要:线程间通信其实就是多个线程操作同一个资源,但动作不同。同步前提是多线程。将该线程载入线程池,等待唤醒。该方法抛出异常,故需要配合使用随机唤醒线程池中一线程。线程为了检测死锁,它需要递进地检测所有被请求的锁。 线程间通信 其实就是多个线程操作同一个资源,但动作不同。示例:在某个数据库中,Input输入人的姓名,性别,Output输出,两个线程同时作用。思考:1.明确哪些代码是多线程操作的...

    CocoaChina 评论0 收藏0
  • Java基础学习——多线程控制线程

    摘要:常用于临时加入线程。重载形式等待被的线程执行完成。当正在运行的线程都是守护线程时,虚拟机退出。为线程对象设置优先级类定义了三个静态常量停止线程释放执行线程的执行权,让重新调度一次,但仍有可能回到该线程。 join()线程当A线程执行到了B线程的join()方法时,A线程就会等待B线程执行完,A线程才会执行。join()常用于临时加入线程。重载形式:join():等待被join的线程执行...

    Keagan 评论0 收藏0

发表评论

0条评论

tomlingtm

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<