java线程操作 sleep wait start wait 等

来源:互联网 发布:oracle导入数据库 编辑:程序博客网 时间:2024/06/07 20:36

(一)1.sleep()

睡眠:线程进入睡眠的时候,就会让出cpu的使用,其他线程就有机会被执行,但是值得注意的是,sleep不会让线程让出对象锁,所以,对于synchronized的函数或者代码块来说,就算当前线程是sleep状态,其他也不能执行。

睡眠的实现:调用静态方法。它只会是使当前线程被sleep,可以将Thread.sleep()的调用放线程run()之内。这样就能使该线程执行过程中会睡眠。
public void run() {
        try {
            Thread.sleep(123);
        } catch (InterruptedException e) {
            e.printStackTrace(); 
        }
}

注意:
1、线程睡眠是帮助所有线程获得运行机会的最好方法。
2、线程睡眠到期自动苏醒,并返回到可运行状态,不是运行状态。sleep()中指定的时间是线程不会运行的最短时间。因此,sleep()方法不能保证该线程睡眠到期后就开始执行。
3、sleep()是静态方法,只能控制当前正在运行的线程。
4.sleep不会让线程让出对象锁,所以也就不会影响其他进程对象的运行。但在sleep的过程中过程中有可能被其他对象调用它的interrupt(),产生InterruptedException异常,如果你的程序不捕获这个异常,线程就会异常终止,进入TERMINATED状态,如果你的程序捕获了这个异常,那么程序就会继续执行catch语句块(可能还有finally语句块)以及以后的代码。

 
扩展 :sleep() 函数 和wait()函数的区别

1、这两个方法来自不同的类,sleep()是Thread,wait()是Object

2、最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。

3、wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用(使用范围)

  synchronized(x){

  x.notify()

  //或者wait()

  }

4、sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常

5.wait属于Object的成员方法,一旦一个对象调用了wait方法,必须要采用notify()和notifyAll()方法唤醒该进程;如果线程拥有某个或某些对象的同步锁,那么在调用了wait()后,这个线程就会释放它持有的所有同步资源,而不限于这个被调用了wait()方法的对象。wait()方法也同样会在wait的过程中有可能被其他对象调用interrupt()方法而产生

InterruptedException,效果以及处理方式同sleep()方法


(二) 线程的中断

以前使用stop来中断线程,现在的jdk已经不支持了,提倡,在run函数中用无限循环 ,然后用布尔值来标记循环的停止。

如:

public void run (){

boolean b = false;

while(true){

//...

   if(b){

     break;

       }

   }

}

 如果线程是用sleep和wait 进入到就绪状态的话, 可以是用interrupt 函数 使得线程离开run函数, 同时 结束线程, 但是会抛出InterruptedException

为了更好地理解interrupt()效果,我们来看一下下面这个例子: 

[java] view plaincopy
  1. public class InterruptTest {  
  2.     public static void main(String[] args) {  
  3.         Thread t = new Thread() {  
  4.             public void run() {  
  5.                 try {  
  6.                     System.out.println("我被执行了-在sleep()方法前");  
  7.                     // 停止运行10分钟  
  8.                     Thread.sleep(1000 * 60 * 60 * 10);  
  9.                     System.out.println("我被执行了-在sleep()方法后");  
  10.                 } catch (InterruptedException e) {  
  11.                     System.out.println("我被执行了-在catch语句块中");  
  12.                 }  
  13.                 System.out.println("我被执行了-在try{}语句块后");  
  14.             }  
  15.         };  
  16.         // 启动线程  
  17.         t.start();  
  18.         // 在sleep()结束前中断它  
  19.         t.interrupt();  
  20.     }  
  21. }  

运行结果: 
  1. 我被执行了-在sleep()方法前
  2. 我被执行了-在catch语句块中
  3. 我被执行了-在try{}语句块后

(三)线程的优先级和线程让步yield()

线程的让步:通过Thread.yield()来实现的。yield()方法的作用是:提醒当前处在运行状态的线程,把资源让给其他线程,但是没有机制保证这种提醒会得到真正的实施。当当前线程放弃执行权回到就绪状态的时候,具有同样优先级的线程就有进入执行的可能。支持多任务的操作系统,会自动为线程分配时间片。
 
线程优先级:JVM线程调度程序是基于优先级的抢先调度机制。在大多数情况下,当前运行的线程优先级将大于或等于线程池中任何线程的优先级。但这仅仅是大多数情况。
线程优先级为1~10之间的正整数,JVM从不会改变一个线程的优先级。然而,1~10之间的值是没有保证的。一些JVM可能不能识别10个不同的值,而将这些优先级进行每两个或多个合并,变成少于10个的优先级,则两个或多个优先级的线程可能被映射为一个优先级。
 
线程默认优先级是5,Thread类中有三个常量,定义线程优先级范围:
static int MAX_PRIORITY
          线程可以具有的最高优先级。
static int MIN_PRIORITY
          线程可以具有的最低优先级。
static int NORM_PRIORITY
          分配给线程的默认优先级。
 
设置线程的优先级:线程默认的优先级是创建它的执行线程的优先级。可以通过setPriority(int newPriority)更改线程的优先级。例如:
        Thread t = new MyThread();
        t.setPriority(8);
        t.start();
 
注意:当设计多线程应用程序的时候,一定不要依赖于线程的优先级。因为线程调度优先级操作是没有保障的,只能把线程优先级作用作为一种提高程序效率的方法,但是要保证程序不依赖这种操作。
 
(四)join()
在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后,需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到join()方法了。
 

写一个简单的例子来看一下join()的用法:

1.AThread 类

2.BThread类

3.TestDemo 类

  1. class BThread extends Thread {    public BThread() {        super("[BThread] Thread");    };    public void run() {        String threadName = Thread.currentThread().getName();        System.out.println(threadName + " start.");        try {            for (int i = 0; i < 5; i++) {                System.out.println(threadName + " loop at " + i);                Thread.sleep(1000);            }            System.out.println(threadName + " end.");        } catch (Exception e) {            System.out.println("Exception from " + threadName + ".run");        }    }}class AThread extends Thread {    BThread bt;    public AThread(BThread bt) {        super("[AThread] Thread");        this.bt = bt;    }    public void run() {        String threadName = Thread.currentThread().getName();        System.out.println(threadName + " start.");        try {            bt.join();            System.out.println(threadName + " end.");        } catch (Exception e) {            System.out.println("Exception from " + threadName + ".run");        }    }}public class TestDemo {    public static void main(String[] args) {        String threadName = Thread.currentThread().getName();        System.out.println(threadName + " start.");        BThread bt = new BThread();        AThread at = new AThread(bt);        try {            bt.start();            Thread.sleep(2000);            at.start();            at.join();        } catch (Exception e) {            System.out.println("Exception from main");        }        System.out.println(threadName + " end!");    }}

    打印结果:

    main start.    //主线程起动,因为调用了at.join(),要等到at结束了,此线程才能向下执行。 [BThread] Thread start. [BThread] Thread loop at 0 [BThread] Thread loop at 1 [AThread] Thread start.    //线程at启动,因为调用bt.join(),等到bt结束了才向下执行。 [BThread] Thread loop at 2 [BThread] Thread loop at 3 [BThread] Thread loop at 4 [BThread] Thread end. [AThread] Thread end.    // 线程AThread在bt.join();阻塞处起动,向下继续执行的结果 main end!      //线程AThread结束,此线程在at.join();阻塞处起动,向下继续执行的结果。

 

 

 

0 0