线程第二天——线程休眠和线程间通信的实现
线程休眠sleep方法详解
线程的休眠是很有必要的,在做服务端的时候为了减少服务器的压力我们需要休眠。如果休眠是在同步代码块中执行。休眠不会让出锁对象(CPU处于等待运行状态)
- 实例代码
public class SleepDemo implements Runnable{
public static void main(String[] args) {
SleepDemo sleepDemo = new SleepDemo();
Thread thread = new Thread(sleepDemo,"时间戳一");
Thread thread1 = new Thread(sleepDemo,"时间戳二");
Thread thread2 = new Thread(sleepDemo,"时间戳三");
Thread thread3 = new Thread(sleepDemo,"时间戳四");
thread.start();
thread1.start();
thread2.start();
thread3.start();
}
private Object obj=new Object();
@Override
public void run() {
while (true) {
synchronized (obj) {
try {
Thread.sleep(1000);
SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date = format.format(new Date());
System.out.println(Thread.currentThread().getName() + ":" + date);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
线程间的通信
生产者生产水果,如果水果没有被买走那么就不生产处于等待状态,如果水果被消费者买走,消费者会通知生产者告诉它我们已经把水果买走请生产。
消费者同理,如果水果以及生产出来那么就买走,买走之后再通知生产者水果以及没了请生产。
- 代码实现
- 资源类 水果
public class Fruit {
private String name;
private boolean isExist;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isExist() {
return isExist;
}
public void setExist(boolean exist) {
isExist = exist;
}
}
- 生产者线程
public class ProductFruit implements Runnable{
private Fruit fruit;
public ProductFruit(Fruit fruit) {
super();
this.fruit = fruit;
}
@Override
public void run() {
while (true) {
//有共享的数据,多个线程操作共享的数据,必须使用锁
synchronized (fruit) {
//如果水果已经存在那么就不生产,等待消费者买走水果在生产
if (fruit.isExist()) {
try {
//当前生产水果的线程被挂起变成阻塞状态
fruit.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(fruit.getName()+"被生产");
fruit.setExist(true);
//唤醒买水果的线程
fruit.notify();
}
}
}
}
}
- 消费者现场
public class BuyFruit implements Runnable{
private Fruit fruit;
public BuyFruit(Fruit fruit) {
super();
this.fruit = fruit;
}
@Override
public void run() {
while (true) {
//有共享的数据,多个线程操作共享的数据,必须使用锁
synchronized (fruit) {
if (!fruit.isExist()) {
try {
fruit.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(fruit.getName()+"被消费");
fruit.setExist(false);
//唤醒生产水果的线程
fruit.notify();
}
}
}
}
}
- 测试客户端
public class Client {
public static void main(String[] args) {
Fruit fruit = new Fruit();
fruit.setName("芒果");
fruit.setExist(false);
ProductFruit productFruit = new ProductFruit(fruit);
BuyFruit buyFruit = new BuyFruit(fruit);
Thread thread = new Thread(productFruit);
Thread thread1 = new Thread(buyFruit);
thread.start();
thread1.start();
}
}
注意:
1、线程间的通信共享数据一定要有同步代码块
2、一定要有wait和notify,而且二者一定是成对出现。
3、生产者和消费者的线程实现一定是在while(true)里面