ackage com.cfl.thread;
public class Thread2 {
private static TestRunnable testRunnable = new TestRunnable();
// 任务数
private static LinkedList<String> tasks = new LinkedList<String>();
// 窗口个数
private static List<Window> windows = new ArrayList<Window>();
public static void main(String[] args) {
for(int i = 1; i <= 80; i++) {
tasks.add(String.valueOf(i));
}
Door door = new Door(3);
// 启动窗口工作
door.begin();
// 暂停所有窗口
try {
Thread.sleep(10*1000);
System.out.println("======== 暂停所有窗口 ========");
door.suspendAll();
} catch (Exception e) {
}
// 恢复所有暂停窗口
try {
Thread.sleep(12*1000);
System.out.println("======== 恢复所有窗口 ========");
door.notSuspendAll();
} catch (Exception e) {
}
// 暂停某个窗口
try {
Thread.sleep(10*1000);
System.out.println("======== 暂停某个窗口 ========");
door.suspend(windows.get(1));
} catch (Exception e) {
}
// 恢复某个窗口
try {
Thread.sleep(12*1000);
System.out.println("======== 恢复某个窗口 ========");
door.notSuspend(windows.get(1));
} catch (Exception e) {
}
// 减少几个窗口
try {
Thread.sleep(20*1000);
System.out.println("======== 减少窗口 ========");
door.remove(1);
} catch (Exception e) {
System.out.println(e.getMessage());
}
// 减掉所有窗口
try {
Thread.sleep(10*1000);
System.out.println("======== 减掉所有窗口 ========");
door.removeAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 增加几个窗口
try {
Thread.sleep(20*1000);
System.out.println("======== 增加窗口 ========");
door.add(5);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
static class Door extends Thread {
private boolean isActive = true;
/**
* 初始化窗口
* @param windowSize 窗口数量
*/
public Door (int windowSize) {
for(int i = 0; i< windowSize; i++) {
Window window = new Window(testRunnable, (windows.size()+1)+"号窗口");
windows.add(window);
}
this.start();
}
@Override
public void run() {
while (isActive) {
}
}
/**
* 开始启动窗口
*/
public void begin() {
for(Window window : windows) {
System.out.println(window.getName()+"开始工作");
window.start();
}
}
/**
* 暂停所有
*/
public void suspendAll() {
for(Window window : windows) {
suspend(window);
}
}
/**
* 暂停某个窗口
* @param window
*/
public void suspend(Window window) {
if(null == window) {
return;
}
if(WindowState.SUSPEND == window.windowState) {
return;
}
window.suspended();
}
/**
* 恢复所有暂停的窗口
*/
public void notSuspendAll() {
for(Window window : windows) {
window.notSuspended();
}
}
/**
* 恢复某个窗口
* @param window
*/
public void notSuspend(Window window) {
if(null == window) {
return;
}
if(WindowState.SUSPEND != window.windowState) {
return;
}
window.notSuspended();
}
/**
* 删除所有窗口
*/
public void removeAll() {
synchronized(windows) {
for(Window window : windows) {
window.shutdown();
}
}
}
/**
* 删除几个窗口
* @param windowSize
*/
public void remove(int windowSize) {
synchronized (windows) {
if(windowSize >= windows.size()) {
removeAll();
}
for(int i = windows.size()-1; i >= windows.size()-windowSize; i--) {
windows.get(i).shutdown();
}
}
}
/**
* 添加窗口
*/
public void add(int windowSize) throws RuntimeException{
if(this.isAlive()) {
synchronized (windows) {
for(int i = 0; i< windowSize; i++) {
String name = (windows.size()+1)+"号窗口";
System.out.println(name+"开始工作");
Window window = new Window(testRunnable, name);
window.start();
windows.add(window);
}
}
} else {
throw new RuntimeException("门诊还未营业");
}
}
}
private enum WindowState {
/**
* FREE: 空闲
* RUNNING:繁忙
* SUSPENDING: 暂停中
* SUSPEND: 暂停
* STOPING:停止中
* STOP: 已停止
*/
FREE,RUNNING,SUSPENDING,SUSPEND,STOPING,STOP;
}
static class Window extends Thread {
private WindowState windowState;
public Window(TestRunnable testRunnable, String name) {
super(testRunnable, name);
this.windowState = WindowState.FREE;
}
public void run() {
while (true) {
if(windowState == WindowState.SUSPEND) {
try {
Thread.sleep(1*1000);
continue;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(windowState == WindowState.SUSPENDING) {
try {
this.windowState = WindowState.SUSPEND;
Thread.sleep(1*1000);
continue;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (tasks) {
if(tasks.isEmpty()) {
try {
System.out.println(Thread.currentThread().getName() + " wait");
tasks.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
super.run();
try {
windowState = WindowState.RUNNING;
int random=(int)(Math.random()*10+1);
Thread.sleep(random*1000);
if(windowState == WindowState.RUNNING) {
windowState = WindowState.FREE;
}
} catch (InterruptedException e) {
if(windowState == WindowState.STOPING) {
// 停止
windowState = WindowState.STOP;
windows.remove(this);
System.out.println(Thread.currentThread().getName() + ": " + windowState);
break;
}
}
}
}
/**
* 停止
*/
public void shutdown() {
this.windowState = WindowState.STOPING;
this.interrupt();
}
/**
* 暂停
*/
public void suspended() {
this.windowState = WindowState.SUSPENDING;
System.out.println(this.getName() + ": " + this.windowState);
}
/**
* 恢复暂停到执行任务
*/
public void notSuspended() {
if(this.windowState == WindowState.SUSPEND) {
this.windowState = WindowState.FREE;
}
}
}
static class TestRunnable implements Runnable {
public synchronized void run() {
synchronized (tasks) {
if(!tasks.isEmpty()) {
String str = tasks.removeFirst();
System.out.println(Thread.currentThread().getName() + ": " + str);
tasks.notifyAll();
}
}
}
}
}
打印结果:
1号窗口开始工作
2号窗口开始工作
3号窗口开始工作
1号窗口: 1
2号窗口: 2
3号窗口: 3
3号窗口: 4
1号窗口: 5
1号窗口: 6
2号窗口: 7
3号窗口: 8
1号窗口: 9
1号窗口: 10
======== 暂停所有窗口 ========
1号窗口: SUSPEND
2号窗口: SUSPEND
3号窗口: SUSPEND
======== 恢复所有窗口 ========
1号窗口: 11
3号窗口: 12
2号窗口: 13
3号窗口: 14
2号窗口: 15
1号窗口: 16
1号窗口: 17
======== 暂停某个窗口 ========
2号窗口: SUSPEND
3号窗口: 18
3号窗口: 19
1号窗口: 20
1号窗口: 21
3号窗口: 22
======== 恢复某个窗口 ========
2号窗口: 23
1号窗口: 24
2号窗口: 25
3号窗口: 26
2号窗口: 27
1号窗口: 28
3号窗口: 29
2号窗口: 30
======== 减少窗口 ========
3号窗口: STOP
1号窗口: 31
2号窗口: 32
1号窗口: 33
1号窗口: 34
======== 减掉所有窗口 ========
1号窗口: STOP
2号窗口: STOP
======== 增加窗口 ========
1号窗口开始工作
2号窗口开始工作
3号窗口开始工作
1号窗口: 35
4号窗口开始工作
2号窗口: 36
5号窗口开始工作
3号窗口: 37
4号窗口: 38
5号窗口: 39
2号窗口: 40
3号窗口: 41
5号窗口: 42
2号窗口: 43
3号窗口: 44
1号窗口: 45
1号窗口: 46
4号窗口: 47
5号窗口: 48
5号窗口: 49
2号窗口: 50
3号窗口: 51
4号窗口: 52
3号窗口: 53
1号窗口: 54
5号窗口: 55
5号窗口: 56
2号窗口: 57
1号窗口: 58
4号窗口: 59
3号窗口: 60
4号窗口: 61
2号窗口: 62
4号窗口: 63
5号窗口: 64
1号窗口: 65
5号窗口: 66
2号窗口: 67
4号窗口: 68
3号窗口: 69
2号窗口: 70
3号窗口: 71
5号窗口: 72
1号窗口: 73
2号窗口: 74
1号窗口: 75
4号窗口: 76
3号窗口: 77
4号窗口: 78
5号窗口: 79
1号窗口: 80
5号窗口 wait
4号窗口 wait
2号窗口 wait
1号窗口 wait
3号窗口 wait
- 因为Runnable实现了逻辑和线程分离,所以可以在Runnable中共享一份数据。
- 因为在Runnable中共享的是同一份数据,所以存在线程安全问题,所以加上了synchronized来控制同步,注意synchronized会导致性能下降。
- synchronized:修饰对象时表明该对象在任何时候只能由一个线程访问(本案例使用)。
- synchronized:修饰某一个方法的后,当一个线程A使用这个方法时,其他线程想使用这个方法就必须等待,直到线程A使用完这个方法。