太难了,学不会,晚上去码头整点儿薯条
一、线程控制
在上一篇笔记中,提到了生命周期。
线程控制就是生命周期状态之间的切换。
1.1常用方法(更多查询API
- 休眠sleep方法
static void sleep(long time) // 让当前线程暂停,不会释放锁。
time 是休眠时间,单位ms
- 守护线程
守护线程是一种特殊的线程,当所有非守护线程结束后,即使守护线程没有运行完也会结束。
final void setDaemon(boolean on) //设置守护线程
- 礼让线程yield方法
把执行权让出去,但是没完全让出去(自身仍然会去抢占线程。
public static void yield()
- 插队线程join方法
当前线程暂停,等待插入线程结束后再继续。
public static void join()
1.2 等待唤醒机制
- 线程等待
void wait()
:会一直处于阻塞状态,直到被唤醒 - 唤醒一个
notify()
:随机唤醒当前对象下,一个等待的线程。 - 唤醒一个
notifyAll()
:唤醒当前对象下,所有等待的线程。
当前对象指的是监视器对象,锁对象带监视器对象。
我们知道锁会把别的线程拒之门外,如果已经有线程在运行的话。这时候等待进来的代码就会放在等待队列中,受这个锁对象的监视器对象监视。不同锁下的线程不能相互唤醒
插一句,同步方法中自动用的是this,也就是说,锁是该方法所在的实例
二、线程通信
上一篇笔记利用同步代码块保证了共享数据的安全性,但是有时候我们需要两个线程交替对数据进行访问。
并发:某一个时刻,处理处理这个,处理处理那个,同一时间点只执行一个任务。
并行:同一时间点,处理不同任务
2.1 利用等待唤醒机制实现交替运行
public class day01{
static int flag = 1;
public static void main(String[] args) {
new Thread() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
synchronized (day01.class){
if(flag == 2){
try {
day01.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(getName() + ":" + i);
day01.class.notify();
flag = 2;
}
}
}
}.start();
new Thread() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
synchronized (day01.class){
if(flag == 1){
try {
day01.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(getName() + ":" + i);
day01.class.notify();
flag = 1;
}
}
}
}.start();
}
}
2.2 生产者消费者模型
进一步扩展,我们可以把交替实现的两个线程看作生产者
和消费者
实际上有时候生产者生产的很快,而消费者很慢,反之亦有之。轮流会降低效率,因此这个模型增加了缓存区。
加入缓存区的好处:
1.提高了效率:
例,生产者生产的时间为:1,5,1,5,1。
消费者消耗所需要的时间:5,1,5,1,5。
那么按照轮流执行所需要的总时间为:1+5+5+1+1+5+5+1+1+5=30
假设有一个长度为2的缓存区,那么需要的时间是:1+5+1+1+1+5=14
2.解耦了生产者和消费者
之前需要生产者和消费者相互通知,现在由缓冲区来进行通知,各司其职,易于维护。
public class SandX {
//生产者和消费者,中间需要一个缓存区
public static void main(String[] args) {
DataBuffer dataBuffer = new DataBuffer(10);
X x = new X(dataBuffer);
S s = new S(dataBuffer);
s.start();
x.start();
}
}
class Data<T>{
private final T data;
Data(T t){ this.data = t; }
public T getData() { return data; }
}
class DataBuffer{
private int index;
final private int capacity;
final private Object[] dataBuffer;
DataBuffer(int capacity){
this.capacity = capacity;
dataBuffer = new Object[capacity];
}
//存数据
public synchronized void push(Data data){
if(index == capacity){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
dataBuffer[index] = data.getData();
index++;
notify();
}
//取数据
public synchronized Object pop(){
if(index == 0){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
index--;
notify();
return dataBuffer[index];
}
}
class S extends Thread{
final private DataBuffer dataBuffer;
public S(DataBuffer dataBuffer){
this.dataBuffer = dataBuffer;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("我正在生产数据:"+i);
Data<Integer> data = new Data<>(i);
dataBuffer.push(data);
}
}
}
class X extends Thread{
final private DataBuffer dataBuffer;
public X(DataBuffer dataBuffer){
this.dataBuffer = dataBuffer;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("我正在消耗数据:"+dataBuffer.pop());
}
}
}
整薯条儿去喽