zoukankan      html  css  js  c++  java
  • 线程学习二:Thread类常用方法

     在正式学习Thread类中的具体方法之前,我们先来了解一下线程有哪些状态,这个将会有助于后面对Thread类中的方法的理解。

      线程从创建到最终的消亡,要经历若干个状态。一般来说,线程包括以下这几个状态:创建(new)、就绪(runnable)、运行(running)、阻塞(blocked)、time waiting、waiting、消亡(dead)。

      当需要新起一个线程来执行某个子任务时,就创建了一个线程。但是线程创建之后,不会立即进入就绪状态,因为线程的运行需要一些条件(比如内存资源,在前面的JVM内存区域划分一篇博文中知道程序计数器、Java栈、本地方法栈都是线程私有的,所以需要为线程分配一定的内存空间),只有线程运行需要的所有条件满足了,才进入就绪状态。

      当线程进入就绪状态后,不代表立刻就能获取CPU执行时间,也许此时CPU正在执行其他的事情,因此它要等待。当得到CPU执行时间之后,线程便真正进入运行状态。

      线程在运行状态过程中,可能有多个原因导致当前线程不继续运行下去,比如用户主动让线程睡眠(睡眠一定的时间之后再重新执行)、用户主动让线程等待,或者被同步块给阻塞,此时就对应着多个状态:time waiting(睡眠或等待一定的事件)、waiting(等待被唤醒)、blocked(阻塞)。

      当由于突然中断或者子任务执行完毕,线程就会被消亡。

      下面这副图描述了线程从创建到消亡之间的状态:

      在有些教程上将blocked、waiting、time waiting统称为阻塞状态,这个也是可以的,只不过这里我想将线程的状态和Java中的方法调用联系起来,所以将waiting和time waiting两个状态分离出来。

    常用方法

    1、start

    start()用来启动一个线程,当调用start方法后,系统才会开启一个新的线程来执行用户定义的子任务,在这个过程中,会为相应的线程分配需要的资源。

    2、run

      run()方法是不需要用户来调用的,当通过start方法启动一个线程之后,当线程获得了CPU执行时间,便进入run方法体去执行具体的任务。注意,继承Thread类必须重写run方法,在run方法中定义具体要执行的任务。

    3、yield

    yield()方法详单与线程调度器,执行该方法后当前线程将交出其CPU使用权限,让别的线程有机会使用CPU。

      实际上,yield()方法对应了如下操作;先检测当前是否有相同优先级的线程处于同可运行状态,如有,则把CPU的占有权交给次线程,否则继续运行原来的线程,所以yield()方法称为“退让”,它把运行机会让给了同等级的其他线程。

     1 public class MainThreadTest implements Runnable {
     2 
     3     public static void main(String[] args) {
     4         Thread aa = new Thread(new MainThreadTest());
     5         Thread bb = new Thread(new MainThreadTest());
     6         aa.start();
     7         bb.start();
     8     }
     9 
    10     @Override
    11     public void run() {
    12         for (int i = 0; i < 100; i++) {
    13             System.out.println(Thread.currentThread().getName() + i);
    14             Thread.yield();
    15         }
    16     }
    17 }

      4、sleep

      调用sleep(long millis)将任务终止mills毫秒

     1 public class ThreadTest implements Runnable {
     2     private int count = 300;
     3 
     4     @Override
     5     public void run() {
     6         for (int i = 0; i < 100; i++) {
     7             System.out.println(Thread.currentThread().getName() + "........" + count--);
     8             try {
     9                 Thread.sleep(1000);
    10             } catch (InterruptedException e) {
    11                 // TODO Auto-generated catch block
    12                 e.printStackTrace();
    13             }
    14         }
    15     }
    16 
    17     public static void main(String[] args) {
    18         ThreadTest aa = new ThreadTest();
    19         Thread t1 = new Thread(aa);
    20         Thread t2 = new Thread(aa);
    21         Thread t3 = new Thread(aa);
    22         t1.start();
    23         t2.start();
    24         t3.start();
    25 
    26     }
    27     
    28 }

    带同步锁调用sleep()方法时

     1 public class MainThreadTest implements Runnable {
     2     private Object object = new Object();
     3 
     4     public static void main(String[] args) throws InterruptedException {
     5         MainThreadTest mtt = new MainThreadTest();
     6         Thread aa = new Thread(mtt);
     7         Thread bb = new Thread(mtt);
     8         aa.start();
     9         bb.start();
    10     }
    11 
    12     @Override
    13     public void run() {
    14         synchronized (object) {
    15             System.out.println(Thread.currentThread().getName() + "进入随眠状态");
    16             try {
    17                 Thread.sleep(1000);
    18             } catch (InterruptedException e) {
    19                 e.printStackTrace();
    20             }
    21             System.out.println(Thread.currentThread().getName() + "结束随眠状态");
    22         }
    23     }
    24 }

      5、getPriority和setPriority

      用来查看和设置线程的优先级,优先级为1到10,默认为5,优先级越大占有CPU时间越久(相对于优先级第的而言,并不是绝对的)

     1 public class ThreadExtendsTest extends Thread { 
     2     public int priority;
     3 
     4     public ThreadExtendsTest(int priority) {
     5         super();
     6         this.priority = priority;
     7     }
     8 
     9     @Override
    10     public void run() {
    11         Thread.currentThread().setPriority(priority);
    12         System.out.println(Thread.currentThread().getName() + Thread.currentThread().getPriority());
    13         for (int i = 0; i < 100; i++) {
    14             System.out.println(this.getName() + "..." + i);
    15 
    16         }
    17     }
    18 
    19     public static void main(String[] args) {
    20         ThreadExtendsTest aa = new ThreadExtendsTest(Thread.MIN_PRIORITY);
    21         ThreadExtendsTest bb = new ThreadExtendsTest(Thread.MAX_PRIORITY);
    22         aa.start();
    23         bb.start();
    24     }
    25 
    26 }

      注意:getPriority和setPriority都有final修饰,是关于线程的属性,调用这两个方法时需要先调用currentThread()方法,类似的还有getId、getName、setName等方法。

      6、jion

      Join()方法把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。

     1 public class MainThreadTest implements Runnable {
     2 
     3     public static void main(String[] args) throws InterruptedException{
     4         Thread aa = new Thread(new MainThreadTest());
     5         aa.start();
     6         for (int i = 0; i < 100; i++) {
     7             System.out.println(Thread.currentThread().getName() + i);
     8             aa.join();
     9         }
    10     }
    11 
    12     @Override
    13     public void run() {
    14         for (int i = 0; i < 100; i++) {
    15             System.out.println(Thread.currentThread().getName() + i);
    16         }
    17     }
    18 }

    7.interrupt

      Thread.interrupt()方法不会中断一个正在运行的线程。它的作用是,在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞的状态。更确切的说,如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞,那么,它将接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态。

     

    在上面已经说到了Thread类中的大部分方法,那么Thread类中的方法调用到底会引起线程状态发生怎样的变化呢?如图所示:

     

    参考资料:

      《Java编程思想》

          http://www.cnblogs.com/dolphin0520/

      http://zy19982004.iteye.com/blog/1626916

      http://www.cnblogs.com/DreamSea/archive/2012/01/11/JavaThread.html#navigation

      http://www.blogjava.net/vincent/archive/2008/08/23/223912.html

      http://iteye.blog.163.com/blog/static/1863080962012111424544215/

      http://blog.csdn.net/lifei128/article/details/20363257

     
  • 相关阅读:
    固定长度下随文字数量增加自动适配字体大小
    vue v-for 和 v-if 、v-else一起使用造成的bug
    火狐使用Ctrl新开窗口不生效
    js如何模拟multipart/form-data类型的请求
    centos安装nodejs
    cursor图标自定义
    解决 vs code 打开文件总是只有一个tab标签页,新打开的tab标签页会替换掉旧的tab标签页
    Devexpress Tab Control 文档
    Devexpress WPF教程
    Linq把一个DataTable根据一列去除重复数据
  • 原文地址:https://www.cnblogs.com/gforce/p/5895650.html
Copyright © 2011-2022 走看看