异常种类:
void notifyAll()
解除所有那些在该对象上调用wait方法的线程的阻塞状态。该方法只能在同步方法或同步块内部调用。如果当前线程不是锁的持有者,该方法抛出一个IllegalMonitorStateException异常。
void notify()
随机选择一个在该对象上调用wait方法的线程,解除其阻塞状态。该方法只能在同步方法或同步块内部调用。如果当前线程不是锁的持有者,该方法抛出一个IllegalMonitorStateException异常。
void wait()
导致线程进入等待状态,直到它被其他线程通过notify()或者notifyAll唤醒。该方法只能在同步方法中调用。如果当前线程不是锁的持有者,该方法抛出一个IllegalMonitorStateException异常。
void wait(long millis)和void wait(long millis,int nanos)
导致线程进入等待状态直到它被通知或者经过指定的时间。这些方法只能在同步方法中调用。如果当前线程不是锁的持有者,该方法抛出一个IllegalMonitorStateException异常。
package com.lzw;
import java.awt.*;
import java.util.*;
import javax.swing.*;
public class SleepMethodTest extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
private Thread t;
// 定义颜色数组
private static Color[] color = { Color.BLACK, Color.BLUE, Color.CYAN,
Color.GREEN, Color.ORANGE, Color.YELLOW, Color.RED,
Color.PINK, Color.LIGHT_GRAY };
private static final Random rand = new Random();// 创建随机对象
private static Color getC() {// 获取随机颜色值的方法
return color[rand.nextInt(color.length)];
}
public SleepMethodTest() {
t = new Thread(new Runnable() {// 创建匿名线程对象
int x = 30;// 定义初始坐标
int y = 50;
public void run() {// 覆盖线程接口方法
while (true) {// 无限循环
try {
Thread.sleep(100);// 线程休眠0.1秒
} catch (InterruptedException e) {
e.printStackTrace();
}
// 获取组件绘图上下文对象
Graphics graphics = getGraphics();
graphics.setColor(getC());// 设置绘图颜色
// 绘制直线并递增垂直坐标
graphics.drawLine(x, y, 100, y++);
if (y >= 80) {
y = 50;
}
}
}
});
t.start();// 启动线程
}
public static void main(String[] args) {
init(new SleepMethodTest(), 100, 100);
}
// 初始化程序界面的方法
public static void init(JFrame frame, int width, int height) {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(width, height);
frame.setVisible(true);
}
}
实验:
实现3个类:Storage、Counter和Printer。 Storage类应存储整数。 Counter应创建线程,线程从0开始计数(0,1,2,3…)并将每个值存储到Storage类中。 Printer类应创建一个线程,线程读取Storage类中的值并打印值。编写程序创建Storage类的实例,并创建一个Counter对象和Printer对象操作此实例。
实验步骤:
(1)、创建三个类Counter, Printer,Storage
(2)、创建TestCounter类,在该类中定义main函数,在main函数中定义Storage对象、Counter对象和 Printer对象,创建Counter线程和Printer线程并启动
(3)、保存文件,调试并编译运行程序。
package test6;
public class Counter extends Thread{
Storage s;
public Counter(){
}
public Counter(String str){
super(str);
}
public Counter(String str, Storage s){
super(str);
this.s = s;
}
public void run(){
synchronized(s) {
System.out.println("Counter开始运行");
for (int i = 0; i < 10; i++){
System.out.println("Counter写入"+(i+1));
try {
s.setNum(i+1);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//s.setNum(i+1);
}
s.notifyAll();
try {
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Counter线程结束运行");
}
}
}
package test6;
public class Printer extends Thread{
Storage s;
public Printer() {
}
public Printer(String str){
super(str);
}
public Printer(String str, Storage s){
super(str);
this.s = s;
}
public void run() {
synchronized(s){
System.out.println("Printer开始运行");
try {
s.wait();
} catch (InterruptedException e1) {
// TODO 自动生成的 catch 块
e1.printStackTrace();
}
for(int i = 0; i < s.num.size(); i++){
//System.out.println(s.num.size()+"~~~~");
System.out.println("Printer输出"+s.GetNum(i));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("Printer结束运行");
}
}
package test6;
import java.util.ArrayList;
public class Storage {
ArrayList num = new ArrayList();
public void setNum(int num){
this.num.add(num);
}
public Object GetNum(int pos){
return num.get(pos);
}
}
package test6;
public class TestCounter {
public static void main(String[] args) {
Storage s = new Storage();
Printer printer = new Printer("Printer",s);
Counter counter = new Counter("Counter",s);
counter.start();
printer.start();
}
}