sleep()方法:表示放弃当前cpu的资源,使当前线程不占用计算机的任何资源。如果当前线程获取到了锁,sleep()方法是不会放弃锁的,如果线程被打断会抛出InterruptException异常。
join()方法:当一个线程对接的join的方法被调用时,调用他的线程会被挂起,直到这个线程对象完成它的任务。
代码:
public class Test3 {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程开始执行");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程执行结束");
}
});
System.out.println("主线程执行");
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("主线程结束");
}
}
执行结果:
主线程执行
线程开始执行
线程执行结束
主线程结束
join方法:
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
可以看出join方法里一直在判断 线程isAlive(),如果存活就wait(0),把线程处于等待状态,如果线程没有执行完成,那么join()这个方法就一直没有执行问,主线程也不会继续往下执行。
wait()方法:线程必须在同步代码块(synchronized)中调用wait()方法,如果在同步代码块之外调用wait()方法,jvm将会抛出IllegalMonitorStateException。当一个线程调用wait()方法时,jvm会把这个线程陷入休眠,并释放掉锁,同时允许其他线程得到锁。
notify()或notifyAll():在同步代码块中调用这2个方法可以唤醒调用wait()的线程。
列子:
public class Computer {
private int counter = 0;
public synchronized void producer() {
while (true) {
if (counter >= 10) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else if (counter < 2) {
for (int i = 0; i < 10; i++) {
counter++;
System.out.println("生产了一台电脑当前还有" + counter);
}
}
notifyAll();
}
}
public synchronized void consumer() {
while (true) {
if (counter == 0) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else if (counter > 0) {
while (counter > 0) {
counter--;
System.out.println("消费一台电脑当前还有" + counter);
}
}
notifyAll();
}
}
public int getCounter() {
return counter;
}
public void setCounter(int counter) {
this.counter = counter;
}
public static void main(String[] args) {
Computer computer = new Computer();
Thread producer = new Thread(new Producer(computer));
Thread consumer = new Thread(new Consumer(computer));
producer.start();
consumer.start();
}
}
public class Consumer implements Runnable{
private Computer computer;
public Consumer(Computer computer) {
super();
this.computer = computer;
}
@Override
public void run() {
computer.consumer();
}
}
public class Producer implements Runnable{
private Computer computer;
public Producer(Computer computer) {
super();
this.computer = computer;
}
@Override
public void run() {
computer.producer();
}
}
输出结果:
生产了一台电脑当前还有8
生产了一台电脑当前还有9
生产了一台电脑当前还有10
消费一台电脑当前还有9
消费一台电脑当前还有8
消费一台电脑当前还有7
消费一台电脑当前还有6
消费一台电脑当前还有5
消费一台电脑当前还有4
消费一台电脑当前还有3
消费一台电脑当前还有2
在ReentrantLock挂起和唤醒线程需要使用Condition,一个ReentrantLock可以有多个Condition。调用await()使线程挂起并释放掉锁,signalAll()会唤醒线程。
修改Compuetr的代码 Producer 和 Consumer 代码 不变:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Computer {
private int counter = 0;
private ReentrantLock lock;
private Condition producerC;
private Condition consumerC;
private Computer(ReentrantLock lock) {
this.lock = lock;
producerC = lock.newCondition();
consumerC = lock.newCondition();
}
public void producer() {
while (true) {
try {lock.lock();
if (counter >= 10) {
try {
//线程挂起 并释放掉锁
producerC.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else if (counter < 2) {
for (int i = 0; i < 10; i++) {
counter++;
System.out.println("生产了一台电脑当前还有" + counter);
}
}
//把线程唤醒 线程需要重新获取锁
consumerC.signalAll();
} finally {
lock.unlock();
}
}
}
public void consumer() {
while (true) {
try {lock.lock();
if (counter == 0) {
try { //线程挂起 并释放掉锁
consumerC.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else if (counter > 0) {
while (counter > 0) {
counter--;
System.out.println("消费一台电脑当前还有" + counter);
}
}
//把线程唤醒 线程需要重新获取锁
producerC.signalAll();
} finally {
lock.unlock();
}
}
}
public int getCounter() {
return counter;
}
public void setCounter(int counter) {
this.counter = counter;
}
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
Computer computer = new Computer(lock);
Thread producer = new Thread(new Producer(computer));
Thread consumer = new Thread(new Consumer(computer));
producer.start();
consumer.start();
}
}