zoukankan      html  css  js  c++  java
  • java线程的常用方法

    java线程的常用方法

    编号方法说明
    1 public void start() 使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
    2 public void run() 如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。
    3 public final void setName(String name) 改变线程名称,使之与参数 name 相同。
    4 public final void setPriority(int priority) 更改线程的优先级。
    5 public final void setDaemon(boolean on) 将该线程标记为守护线程或用户线程。
    6 public final void join(long millisec) 等待该线程终止的时间最长为 millis 毫秒。
    7 public void interrupt() 中断线程。
    8 public final boolean isAlive() 测试线程是否处于活动状态。
    9 public static void yield() 暂停当前正在执行的线程对象,并执行其他线程。
    10 public static void sleep(long millisec) 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。
    11 public static Thread currentThread() 返回对当前正在执行的线程对象的引用。

     

    一:静态方法

    (1)currentThread()方法

    currentThread()方法可以返回代码段正在被哪个线程调用的信息。

    1
    2
    3
    4
    5
    public class Run1{
        public static void main(String[] args){                
        System.out.println(Thread.currentThread().getName());
        }
    }

    (2)sleep()方法

    方法sleep()的作用是在指定的毫秒数内让当前“正在执行的线程”休眠(暂停执行)。这个“正在执行的线程”是指this.currentThread()返回的线程。

    sleep方法有两个重载版本:

    1
    2
    sleep(long millis)     //参数为毫秒
    sleep(long millis,int nanoseconds)    //第一参数为毫秒,第二个参数为纳秒

    sleep相当于让线程睡眠,交出CPU,让CPU去执行其他的任务。
    但是有一点要非常注意,sleep方法不会释放锁,也就是说如果当前线程持有对某个对象的锁,则即使调用sleep方法,其他线程也无法访问这个对象。看下面这个例子就清楚了:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    public class Test {
     
        private int i = 10;
        private Object object = new Object();
     
        public static void main(String[] args) throws IOException  {
            Test test = new Test();
            MyThread thread1 = test.new MyThread();
            MyThread thread2 = test.new MyThread();
            thread1.start();
            thread2.start();
        }
     
        class MyThread extends Thread{
            @Override
            public void run() {
                synchronized (object) {
                    i++;
                    System.out.println("i:"+i);
                    try {
                        System.out.println("线程"+Thread.currentThread().getName()+"进入睡眠状态");
                        Thread.currentThread().sleep(10000);
                    } catch (InterruptedException e) {
                        // TODO: handle exception
                    }
                    System.out.println("线程"+Thread.currentThread().getName()+"睡眠结束");
                    i++;
                    System.out.println("i:"+i);
                }
            }
        }
    }

    输出结果:

    从上面输出结果可以看出,当Thread-0进入睡眠状态之后,Thread-1并没有去执行具体的任务。只有当Thread-0执行完之后,此时Thread-0释放了对象锁,Thread-1才开始执行。

    注意,如果调用了sleep方法,必须捕获InterruptedException异常或者将该异常向上层抛出。当线程睡眠时间满后,不一定会立即得到执行,因为此时可能CPU正在执行其他的任务。所以说调用sleep方法相当于让线程进入阻塞状态。

    (3)yield()方法

    调用yield方法会让当前线程交出CPU权限,让CPU去执行其他的线程。它跟sleep方法类似,同样不会释放锁。但是yield不能控制具体的交出CPU的时间,另外,yield方法只能让拥有相同优先级的线程有获取CPU执行时间的机会。

    注意,调用yield方法并不会让线程进入阻塞状态,而是让线程重回就绪状态,它只需要等待重新获取CPU执行时间,这一点是和sleep方法不一样的。
    代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    public class MyThread  extends Thread{
        @Override
        public void run() {
            long beginTime=System.currentTimeMillis();
            int count=0;
            for (int i=0;i<50000000;i++){
                count=count+(i+1);
                //Thread.yield();
            }
            long endTime=System.currentTimeMillis();
            System.out.println("用时:"+(endTime-beginTime)+" 毫秒!");
        }
    }
     
    public class Run {
        public static void main(String[] args) {
            MyThread t= new MyThread();
            t.start();
        }
    }

    执行结果:

    1
    用时:3 毫秒!

    如果将 //Thread.yield();的注释去掉,执行结果如下:

    1
    用时:16080 毫秒!

    二:对象方法

    (1)start()方法

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

    (2)run()方法

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

    (3)getId()

    getId()的作用是取得线程的唯一标识
    代码:

    1
    2
    3
    4
    5
    6
    public class Test {
        public static void main(String[] args) {
            Thread t= Thread.currentThread();
            System.out.println(t.getName()+" "+t.getId());
        }
    }

    输出:

    1
    main 1

    (4)isAlive()方法

    方法isAlive()的功能是判断当前线程是否处于活动状态
    代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public class MyThread  extends Thread{
        @Override
        public void run() {
            System.out.println("run="+this.isAlive());
        }
    }
    public class RunTest {
        public static void main(String[] args) throws InterruptedException {
            MyThread myThread=new MyThread();
            System.out.println("begin =="+myThread.isAlive());
            myThread.start();
            System.out.println("end =="+myThread.isAlive());
        }
    }

    程序运行结果:

    1
    2
    3
    begin ==false
    run=true
    end ==false

    方法isAlive()的作用是测试线程是否偶处于活动状态。什么是活动状态呢?活动状态就是线程已经启动且尚未终止。线程处于正在运行或准备开始运行的状态,就认为线程是“存活”的。
    有个需要注意的地方

    1
    System.out.println("end =="+myThread.isAlive());

    虽然上面的实例中打印的值是true,但此值是不确定的。打印true值是因为myThread线程还未执行完毕,所以输出true。如果代码改成下面这样,加了个sleep休眠:

    1
    2
    3
    4
    5
    6
    7
    public static void main(String[] args) throws InterruptedException {
            MyThread myThread=new MyThread();
            System.out.println("begin =="+myThread.isAlive());
            myThread.start();
            Thread.sleep(1000);
            System.out.println("end =="+myThread.isAlive());
        }

    则上述代码运行的结果输出为false,因为mythread对象已经在1秒之内执行完毕。

    (5)join()方法

    在很多情况下,主线程创建并启动了线程,如果子线程中药进行大量耗时运算,主线程往往将早于子线程结束之前结束。这时,如果主线程想等待子线程执行完成之后再结束,比如子线程处理一个数据,主线程要取得这个数据中的值,就要用到join()方法了。方法join()的作用是等待线程对象销毁。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public class Thread4 extends Thread{
        public Thread4(String name) {
            super(name);
        }
        public void run() {
            for (int i = 0; i < 5; i++) {
                System.out.println(getName() + "  " + i);
            }
        }
        public static void main(String[] args) throws InterruptedException {
            // 启动子进程
            new Thread4("new thread").start();
            for (int i = 0; i < 10; i++) {
                if (i == 5) {
                    Thread4 th = new Thread4("joined thread");
                    th.start();
                    th.join();
                }
                System.out.println(Thread.currentThread().getName() + "  " + i);
            }
        }
    }

    执行结果:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    main  0
    main  1
    main  2
    main  3
    main  4
    new thread  0
    new thread  1
    new thread  2
    new thread  3
    new thread  4
    joined thread  0
    joined thread  1
    joined thread  2
    joined thread  3
    joined thread  4
    main  5
    main  6
    main  7
    main  8
    main  9

    由上可以看出main主线程等待joined thread线程先执行完了才结束的。如果把th.join()这行注释掉,运行结果如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    main  0
    main  1
    main  2
    main  3
    main  4
    main  5
    main  6
    main  7
    main  8
    main  9
    new thread  0
    new thread  1
    new thread  2
    new thread  3
    new thread  4
    joined thread  0
    joined thread  1
    joined thread  2
    joined thread  3
    joined thread  4

    (6)getName和setName

    用来得到或者设置线程名称。

    (7)getPriority和setPriority

    用来获取和设置线程优先级。

    (8)setDaemon和isDaemon

    用来设置线程是否成为守护线程和判断线程是否是守护线程。

    守护线程和用户线程的区别在于:守护线程依赖于创建它的线程,而用户线程则不依赖。举个简单的例子:如果在main线程中创建了一个守护线程,当main方法运行完毕之后,守护线程也会随着消亡。而用户线程则不会,用户线程会一直运行直到其运行完毕。在JVM中,像垃圾收集器线程就是守护线程。

    在上面已经说到了Thread类中的大部分方法,那么Thread类中的方法调用到底会引起线程状态发生怎样的变化呢?下面一幅图就是在上面的图上进行改进而来的:

  • 相关阅读:
    HDFS DataNode 多目录
    HDFS DataNode 退役 旧节点
    HDFS DateNoda 服役 新节点
    HDFS DataNode 时限参数设置
    HDFS NameNode 多目录
    HDFS 安全模式
    HDFS NameNode故障排除
    HDFS CheckPoint时间设置
    HDFS NameNode和SecondaryNameNode
    微信小程序:上拉加载更多
  • 原文地址:https://www.cnblogs.com/tutubaobao/p/10050169.html
Copyright © 2011-2022 走看看