java线程操作 sleep wait start wait 等

(一)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 plain copy
  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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中的线程等待(wait)是一种用于线程间同步的机制。当一个线程调用对象的`wait()`方法时,它会释放该对象上的锁,并且进入等待状态,直到其他线程通过调用相同对象上的`notify()`或`notifyAll()`方法来唤醒它。 `wait()`方法必须在同步代码块或同步方法中使用,因为它要求线程先获得对象的锁才能调用。当线程调用`wait()`方法后,它会释放持有的锁,其他线程可以访问该对象并执行同步代码块或同步方法。当线程被唤醒后,它会重新尝试获得锁,并继续执行。 下面是一个简单的示例代码,演示了如何使用`wait()`和`notify()`方法实现线程等待: ```java class MyRunnable implements Runnable { private final Object lock; public MyRunnable(Object lock) { this.lock = lock; } @Override public void run() { synchronized (lock) { try { System.out.println("Thread waiting..."); lock.wait(); // 线程等待 System.out.println("Thread resumed!"); } catch (InterruptedException e) { e.printStackTrace(); } } } } public class Main { public static void main(String[] args) throws InterruptedException { Object lock = new Object(); Thread thread = new Thread(new MyRunnable(lock)); thread.start(); // 主线程等待一段时间后唤醒等待的线程 Thread.sleep(2000); synchronized (lock) { lock.notify(); // 唤醒等待的线程 } } } ``` 在这个示例中,线程通过调用`lock.wait()`方法进入等待状态,并且在主线程中通过调用`lock.notify()`方法将其唤醒。注意,`wait()`和`notify()`方法必须在同步代码块(这里是`synchronized (lock)`)中使用。 请注意,线程在被唤醒后,并不会立即执行,而是需要重新竞争锁资源。因此,在`notify()`方法调用之后,等待的线程可能不会立即继续执行,而是需要等待其他线程释放锁才能执行。 这是Java线程等待的基本概念和用法,希望对你有所帮助!如果有更多问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值