[Java并发]
sleep()、wait()、join()、yield()
yield
在Java中,yield() 是一个Thread类的方法,它用于暂停当前线程并允许其他线程运行。它是一种线程调度的建议,告诉调度器可以切换到其他就绪状态的线程。调用yield()方法后,线程会从运行状态转换为就绪状态,让其他线程有机会执行。
下面是一个简单的Java代码示例,展示了yield()方法的用法:
public class YieldExample implements Runnable {
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
// 调用 yield() 方法
Thread.yield();
}
}
public static void main(String[] args) {
// 创建两个线程
Thread thread1 = new Thread(new YieldExample(), "Thread 1");
Thread thread2 = new Thread(new YieldExample(), "Thread 2");
// 启动线程
thread1.start();
thread2.start();
}
}
在上面的示例中,我们创建了两个线程并启动它们。每个线程都会打印从0到4的数字。在每次循环中,我们调用了yield()方法,这样两个线程就可以交替执行,让出CPU时间给其他线程。
请注意,yield()方法的调用并不能保证当前线程一定会让出CPU时间,它只是一个建议。实际执行结果取决于操作系统和线程调度器的具体实现。
join
在Java中,join() 是Thread类的一个方法,用于等待调用该方法的线程执行完毕。当一个线程调用另一个线程的 join() 方法时,调用线程将被阻塞,直到被调用的线程执行完毕。
join() 方法有以下两种常见的用法:
- 使用
join()方法等待单个线程完成:
Thread thread = new Thread(new MyRunnable());
thread.start();
// 在主线程中调用 join() 方法等待 thread 线程执行完毕
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread 执行完毕");
在上面的示例中,我们创建了一个新线程并启动它。在主线程中,我们调用了join()方法等待新线程执行完毕。主线程会被阻塞,直到新线程执行完毕后才会继续执行。
- 使用
join()方法等待多个线程完成:
Thread thread1 = new Thread(new MyRunnable());
Thread thread2 = new Thread(new MyRunnable());
thread1.start();
thread2.start();
// 在主线程中分别调用 join() 方法等待 thread1 和 thread2 线程执行完毕
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread1 和 thread2 执行完毕");
在上面的示例中,我们创建了两个新线程,并启动它们。然后在主线程中分别调用两个线程的 join() 方法,以等待它们执行完毕。主线程会被阻塞,直到两个线程都执行完毕后才会继续执行。
需要注意的是,join() 方法可能会抛出 InterruptedException,因此在使用时需要处理异常。这是由于线程在等待期间可能被中断,导致 join() 方法提前返回。
使用 join() 方法可以实现线程之间的协作和同步,确保某个线程在其他线程执行完毕后再继续执行。
sleep
在Java中,sleep() 是Thread类的一个静态方法,用于暂停当前线程的执行一段指定的时间。它是一种线程睡眠的机制。
sleep() 方法有以下两种常见的用法:
- 使用
sleep()方法暂停当前线程的执行:
try {
// 暂停当前线程执行 500 毫秒(0.5 秒)
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程睡眠后继续执行");
在上面的示例中,我们使用 sleep() 方法暂停当前线程的执行。在这个例子中,当前线程将会睡眠500毫秒(0.5秒),然后继续执行后续的代码。
需要注意的是,sleep() 方法可能会抛出 InterruptedException,因此在使用时需要处理异常。这是由于线程在睡眠期间可能被中断,导致 sleep() 方法提前返回。
- 使用
sleep()方法实现定时任务:
class MyTask implements Runnable {
public void run() {
try {
// 定时任务,每隔 1 秒执行一次
while (true) {
System.out.println("执行定时任务");
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// 创建一个新线程执行定时任务
Thread thread = new Thread(new MyTask());
thread.start();
在上面的示例中,我们创建了一个新线程来执行定时任务。在定时任务的循环中,我们使用 sleep() 方法使线程睡眠1秒,然后再执行下一次循环。这样就可以实现定时任务的效果。
需要注意的是,sleep() 方法会暂停当前线程的执行,但不会释放锁。如果在同步代码块或同步方法中调用 sleep() 方法,其他线程仍然无法获取到该锁。因此,在使用 sleep() 方法时要注意对锁的使用,避免可能的线程竞争和死锁问题。
总结:
sleep() 方法用于暂停当前线程的执行一段指定的时间。它可以用于实现线程的延时执行、定时任务等场景。然而,需要注意处理可能抛出的 InterruptedException 异常,并避免在同步代码块或同步方法中使用 sleep() 方法导致的线程竞争和死锁问题。
wait
在Java中,wait() 是Object类的一个方法,用于使当前线程进入等待状态,直到其他线程调用相同对象上的 notify() 或 notifyAll() 方法来唤醒等待线程。
wait() 方法有以下常见的用法:
- 在同步代码块中使用
wait()方法:
synchronized (sharedObject) {
try {
// 当前线程进入等待状态,释放对象的锁
sharedObject.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 当线程被唤醒后,继续执行
System.out.println("线程被唤醒");
}
在上面的示例中,我们在一个同步代码块中调用了 wait() 方法。当线程执行到 wait() 方法时,它会释放对象的锁并进入等待状态,直到其他线程调用相同对象上的 notify() 或 notifyAll() 方法来唤醒等待线程。
需要注意的是,在调用 wait() 方法前必须获得对象的锁,因此通常在同步代码块或同步方法中使用 wait() 方法。
- 使用
wait()方法实现线程间的协作:
class MyTask implements Runnable {
private final Object lock;
public MyTask(Object lock) {
this.lock = lock;
}
public void run() {
synchronized (lock) {
try {
System.out.println("线程开始执行任务");
// 执行任务的一部分
// 等待其他线程完成特定条件
lock.wait();
// 线程被唤醒后继续执行任务的剩余部分
System.out.println("线程继续执行任务");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// 创建一个共享的锁对象
Object lock = new Object();
// 创建一个新线程执行任务
Thread thread = new Thread(new MyTask(lock));
thread.start();
// 在适当的时机唤醒等待的线程
synchronized (lock) {
lock.notify();
}
在上面的示例中,我们创建了一个共享的锁对象,并在一个新线程的任务中使用 wait() 方法进行等待。主线程在适当的时机调用 notify() 方法来唤醒等待的线程。
需要注意的是,wait() 方法必须在同步块中使用,并且在调用 wait() 方法前必须获得对象的锁,否则会抛出 IllegalMonitorStateException 异常。
总结:
wait() 方法用于使当前线程进入等待状态,直到其他线程调用相同对象上的 notify() 或 notifyAll() 方法来唤醒等待线程。它常用于线程间的协作和同步。需要在同步块中使用 wait() 方法,并在调用 wait() 方法前获得对象的锁。同时,需要注意处理可能抛出的 InterruptedException 异常和使用适当的唤醒机制。