[多线程] 线程中的常用方法-最详细

线程中常用的方法

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 piority) 更改线程的优先级。

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 static yield() 暂停当前正在执行的线程对象,并执行其他线程。

10、public static void sleep(long millisec) 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。

11、public static Thread currentThread() 返回对当前正在执行的线程对象的引用。

配一张图:

 

静态方法:

1、currentThread()方法

    public static void main(String[] args) {

        System.out.println(Thread.currentThread().getName());
    }

结果:

main

因为是在main函数中运行的,所以得到的名字是main

 

2、sleep()方法

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

sleep方法有两个重载版本

        Thread.sleep(int millis);//参数为休眠的毫秒
        Thread.sleep(int millis, int nanos);//第一个为休眠的毫秒,第二个为纳秒

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

 1 /**
 2  * 线程的sleep方法
 3  *
 4  */
 5 public class SleepMethod {
 6     private int i = 10;
 7     private Object object = new Object();
 8 
 9     public static void main(String[] args) {
10         SleepMethod sm = new SleepMethod();
11         MyThread t1 = sm.new MyThread();
12         MyThread t2 = sm.new MyThread();
13         t1.start();
14         t2.start();
15     }
16 
17     class MyThread extends Thread {
18         @Override
19         public void run() {
20             synchronized (object) {
21                 i++;
22 
23                 try {
24                     System.out.println("I:" + i);
25                     System.out.println("Thread Name:" + Thread.currentThread().getName() + ",进入睡眠");
26                     Thread.sleep(1000);
27                 } catch (InterruptedException e) {
28                     e.printStackTrace();
29                 }
30                 System.out.println("Thread Name:" + Thread.currentThread().getName() + "睡眠结束");
31                 i++;
32                 System.out.println("I" + i);
33             }
34         }
35     }
36 }

运行结果为:

I:11
Thread Name:Thread-0,进入睡眠
Thread Name:Thread-0睡眠结束
I:12
I:13
Thread Name:Thread-1,进入睡眠
Thread Name:Thread-1睡眠结束
I:14

当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  * yield方法
 3  *
 4  */
 5 public class YieldMethod {
 6     class MyThread extends Thread {
 7         @Override
 8         public void run() {
 9 
10             long beginTime=System.currentTimeMillis();
11             int count=0;
12             for(int i=0;i<50000000;i++){
13                 count = count+(i+1);
14                 Thread.yield();
15             }
16             long endTime=System.currentTimeMillis();
17             System.out.println("用时:"+(endTime-beginTime)+"(ms)");
18 
19         }
20     }
21     public static void main(String[] args) {
22         Thread t1=new YieldMethod().new MyThread();
23         t1.start();
24     }
25 }

结果:

用时:26003(ms)

注释掉 Thread.yilde(); 之后:

用时:50(ms)

 

对象方法:

1、start()方法

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

2、run()方法

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

3、getId()方法

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

/**
 * getId方法
 *
 */
public class GetidMethod {
    public static void main(String[] args) {
        Thread t1 = Thread.currentThread();
        System.out.println(t1.getId());
    }
}

输出:

1

 

4、isAlive()方法

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

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

运行结果:

begin:false
end:true
IsAlive:true

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

 System.out.println("IsAlive:" + this.isAlive());

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

 1 public static void main(String[] args) {
 2         Thread t1 = new IsAliveMethod().new MyThread();
 3 
 4         try {
 5             System.out.println("begin:" + t1.isAlive());
 6             t1.start();
 7             t1.sleep(1000);
 8             System.out.println("end:" + t1.isAlive());
 9         } catch (InterruptedException e) {
10             e.printStackTrace();
11         }
12 
13     }
14 }

 

结果:

begin:false
IsAlive:true
end:false

因为mythread对象已经在1秒之内执行完毕。

 

5、join()方法 

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

 

 1 /**
 2  * join方法
 3  *
 4  */
 5 public class JoinMethod extends Thread {
 6     public static void main(String[] args) {
 7         new JoinMethod("JoinMethod").start();
 8         for (int i = 0; i < 10; i++) {
 9             if (i == 5) {
10                 
11                 try {
12                     JoinMethod t1 = new JoinMethod("JoinedMethod main Thread:");
13                     t1.start();
14                     t1.join();
15                 } catch (InterruptedException e) {
16                     e.printStackTrace();
17                 }
18             }
19             System.out.println(Thread.currentThread().getName()+":"+i);
20         }
21     }
22 
23     @Override
24     public void run() {
25         for (int i = 0; i < 5; i++) {
26             System.out.println(getName() + ":\t" + i);
27         }
28     }
29 
30     public JoinMethod(String name) {
31         super(name);
32     }
33 }

 

运行结果:

main:0
JoinMethod:    0
JoinMethod:    1
main:1
JoinMethod:    2
main:2
JoinMethod:    3
JoinMethod:    4
main:3
main:4
JoinedMethod main Thread::    0
JoinedMethod main Thread::    1
JoinedMethod main Thread::    2
JoinedMethod main Thread::    3
JoinedMethod main Thread::    4
main:5
main:6
main:7
main:8
main:9

 

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

main:0
JoinMethod:    0
main:1
JoinMethod:    1
main:2
JoinMethod:    2
main:3
JoinMethod:    3
main:4
JoinMethod:    4
main:5
main:6
main:7
main:8
main:9
JoinedMethod main Thread::    0
JoinedMethod main Thread::    1
JoinedMethod main Thread::    2
JoinedMethod main Thread::    3
JoinedMethod main Thread::    4

 

6、getName()setName() 用来得到或者设置线程名称

 7、getPriority()setPriority() 用来获取和设置线程优先级。

8、setDaemon()isDaemon() 用来设置线程是否成为守护线程和判断线程是否是守护线程。

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

 

线程调用不同的方法变为何种状态呢?

posted @ 2018-03-20 13:10  1440min  阅读(6712)  评论(1编辑  收藏  举报