- sleep(Thread类方法)
- 当调用 Thread.sleep(long millis) 睡眠方法时,就会使当前线程进入阻塞状态;当时间结束之后,线程会重新进入就绪状态;
- 如果当前线程获得了一把同步锁,则 sleep方法阻塞期间,是不会释放锁的;
- join(Thread类方法)
- 当A线程调用B线程的join方法时,A就会进入阻塞状态;直到B线程执行完毕,A才会由阻塞状态转为就绪状态;代码示例:t1、t2、t3三个线程顺序执行:
public class TestJoin {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new MultiT("a"));
Thread t2 = new Thread(new MultiT("b"));
Thread t3 = new Thread(new MultiT("c"));
t1.start();
t1.join();
t2.start();
t2.join();
t3.start();
t3.join();
}
}
class MultiT implements Runnable{
private String s;
private int i;
public MultiT(String s){
this.s = s;
}
@ Override
public void run() {
while(i<10){
System.out.println(s+"===="+i++);
}
}
}
- yield(Thread类方法)
- Thread.yield 方法会使当前线程放弃CPU时间片,把执行机会让给相同或更高优先级的线程;
- 此时当前线程不会阻塞,只是进入了就绪状态,随时可以再次获得CPU时间片,从而进入运行状态;
- yield方法,并不能保证,其它相同或更高优先级的线程一定会获得执行权,也有可能,再次被当前线程拿到执行权;
- yeild方法与sleep一样,不会释放锁资源;代码示例: 既然yield不释放锁,那为什么还要放弃执行权呢。就算放弃了执行权,别的线程也无法获得锁啊
public class TestYield {
public static void main(String[] args) {
YieldThread yieldThread = new YieldThread();
for (int i = 0; i < 10; i++) {
Thread t = new Thread(yieldThread);
t.start();
}
}
}
class YieldThread implements Runnable {
private int count = 0;
@Override
public synchronized void run() {
for (int i = 0; i < 10; i++) {
count ++;
if(count == 1){
Thread.yield();
System.out.println("线程:"+Thread.currentThread().getName() + "让步");
}
System.out.println("线程:"+Thread.currentThread().getName() + ",count:"+count);
}
}
}
结果:
线程:Thread-0让步
线程:Thread-0,count:1
线程:Thread-0,count:2
线程:Thread-0,count:3
线程:Thread-0,count:4
线程:Thread-0,count:5
线程:Thread-0,count:6
线程:Thread-0,count:7
线程:Thread-0,count:8
线程:Thread-0,count:9
线程:Thread-0,count:10
线程:Thread-0,count:11
线程:Thread-0,count:12
- wait、notify、notifyAll(Object的方法)
- 调用线程的wait方法会使当前线程等待,直到其它线程调用此对象的notify/notifyAll方法;
- 当前对象锁有N个线程在等待,则notify方法会随机唤醒其中一个线程,而notifyAll会唤醒对象锁中所有的线程;
- 注意,需要配合 synchronized关键字来使用,唤醒时,不会立马释放锁,只有当前线程执行完之后,才会把锁释放;生产者和消费者示例:
//商店类(Shop):定义一个成员变量,表示第几个面包,提供生产面包和消费面包的操作
public class Shop {
private int bread = 0;
private final int MAX_NUM = 5;
private Object synObj = new Object();
//生产面包
public void produceBread() {
synchronized(synObj){
while (bread == MAX_NUM) {
System.out.println(Thread.currentThread().getName() + ":已经生产完" + bread + "个面包");
synObj.wait(); //到达生产上限,等待其他线程消费
}
bread++;
System.out.println(Thread.currentThread().getName() + ":开始生产第" + bread + "个面包");
synObj.notifyAll(); // 唤醒所有消费者线程
}
}
//消费面包
public void consumeBread() {
synchronized(synObj){
while (bread == 0) {
System.out.println(Thread.currentThread().getName() + ":已经消费完,剩余" + bread + "个面包");
synObj.wait(); //已经消费完面包,等待其他线程生产
}
bread--;
System.out.println(Thread.currentThread().getName() + ":开始消费,剩余" + bread + "个面包");
synObj.notifyAll(); // 唤醒所有生产者线程
}
}
}
//生产者类(Producer):实现 Runnable 接口,重写 run() 方法,调用生产面包的操作
public class Producer extends Thread {
private Shop shop;
public Producer(Shop shop) {
this.shop = shop;
}
@Override
public void run() {
System.out.println(getName() + ":开始生产面包.....");
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
shop.produceBread();
}
}
}
//消费者类( Consumer ):实现 Runnable 接口,重写 run() 方法,调用消费面包的操作
public class Consumer extends Thread {
private Shop shop;
public Consumer(Shop shop) {
this.shop = shop;
}
@Override
public void run() {
System.out.println(getName() + ":开始消费面包.....");
while (true) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
shop.consumeBread();
}
}
}
- awiat、signal、signalAll(juc包中的 condition 类)
- 作用同上,一般配合 lock 使用;消费者和生产者示例:
//商店类(Shop):定义一个成员变量,表示第几个面包,提供生产面包和消费面包的操作
public class Shop {
private int bread = 0;
private final int MAX_NUM = 5;
private ReentrantLock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
//生产面包
public void produceBread() {
lock.lock();
try{
while (bread == MAX_NUM) {
System.out.println(Thread.currentThread().getName() + ":已经生产完" + bread + "个面包");
condtion.await(); //到达生产上限,等待其他线程消费
}
bread++;
System.out.println(Thread.currentThread().getName() + ":开始生产第" + bread + "个面包");
condition.signalAll(); // 唤醒所有消费者线程
}
catch(InterruptedException e){
e.printStackTrace();
}
finally{
lock.unlock();
}
}
//消费面包
public synchronized void consumeBread() {
lock.lock();
try{
while (bread == 0) {
System.out.println(Thread.currentThread().getName() + ":已经消费完,剩余" + bread + "个面包");
condition.await(); //已经消费完面包,等待其他线程生产
}
bread--;
System.out.println(Thread.currentThread().getName() + ":开始消费,剩余" + bread + "个面包");
condition.signalAll(); // 唤醒所有生产者线程
}
catch(InterruptedException e){
e.printStackTrace();
}
finally{
lock.unlock();
}
}
}
//生产者类(Producer):实现 Runnable 接口,重写 run() 方法,调用生产面包的操作
public class Producer extends Thread {
private Shop shop;
public Producer(Shop shop) {
this.shop = shop;
}
@Override
public void run() {
System.out.println(getName() + ":开始生产面包.....");
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
shop.produceBread();
}
}
}
//消费者类(Consumer):实现 Runnable 接口,重写 run() 方法,调用消费面包的操作
public class Consumer extends Thread {
private Shop shop;
public Consumer(Shop shop) {
this.shop = shop;
}
@Override
public void run() {
System.out.println(getName() + ":开始消费面包.....");
while (true) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
shop.consumeBread();
}
}
}