From 38503e0abe24111d92c385903ef427b7da970214 Mon Sep 17 00:00:00 2001 From: Setekhid Date: Wed, 19 Oct 2011 17:59:55 +0800 Subject: [PATCH] add a newer timer and two files to test it --- demo/chat/Telnet_ChatRoom.java | 22 ++--- demo/test/EventGroup_Test.java | 91 ++++++++++++++++++ demo/test/Timer_Test.java | 88 +++++++++++++++++ src/mfw/timer/newer/ClockThread.java | 155 ++++++++++++++++++++++++++++++ src/mfw/timer/newer/ClockThreadGroup.java | 58 +++++++++++ src/mfw/timer/newer/Event.java | 23 +++++ src/mfw/timer/newer/EventGroup.java | 60 ++++++++++++ src/mfw/timer/newer/TimerEvent.java | 28 ++++++ 8 files changed, 514 insertions(+), 11 deletions(-) create mode 100644 demo/test/EventGroup_Test.java create mode 100644 demo/test/Timer_Test.java create mode 100755 src/mfw/timer/newer/ClockThread.java create mode 100644 src/mfw/timer/newer/ClockThreadGroup.java create mode 100644 src/mfw/timer/newer/Event.java create mode 100755 src/mfw/timer/newer/EventGroup.java create mode 100755 src/mfw/timer/newer/TimerEvent.java diff --git a/demo/chat/Telnet_ChatRoom.java b/demo/chat/Telnet_ChatRoom.java index 66a7f49..8a4f8b5 100755 --- a/demo/chat/Telnet_ChatRoom.java +++ b/demo/chat/Telnet_ChatRoom.java @@ -80,14 +80,14 @@ public class Telnet_ChatRoom { }; public static Set list = new HashSet(); - - private static TimerEventGroup timer=new TimerEventGroup(); - - private static byte[] content=new byte[0]; + + private static TimerEventGroup timer = new TimerEventGroup(); + + private static byte[] content = new byte[0]; public static void main(String[] args) throws IOException { Mission.begin(256); - new ClockThread(timer,30000).start(); + new ClockThread(timer, 30000).start(); timer.add(new CleanTimer()); timer.add(new PubTimer()); srv.setWelcomeStr("Welcome!\r\n".getBytes()); @@ -154,16 +154,16 @@ public class Telnet_ChatRoom { flag = false; } } - - public static class Pub extends Trigger{ + + public static class Pub extends Trigger { protected void execute(Returnable subject, Parameter param) { - content=param.getBytes(); + content = param.getBytes(); } } - static class PubTimer extends TimerEvent{ - + static class PubTimer extends TimerEvent { + protected boolean isContinue() { Iterator iter = list.iterator(); while (iter.hasNext()) { @@ -172,7 +172,7 @@ public class Telnet_ChatRoom { return true; } } - + static class CleanTimer extends TimerEvent { protected boolean isContinue() { diff --git a/demo/test/EventGroup_Test.java b/demo/test/EventGroup_Test.java new file mode 100644 index 0000000..6cced1c --- /dev/null +++ b/demo/test/EventGroup_Test.java @@ -0,0 +1,91 @@ +/** + * Copyright 2011 Huize Dai + * + * This file is part of MFW. + * + * MFW is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MFW is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with MFW. If not, see . + */ +package test; + +import test.Timer_Test.TimerEventImpl; +import mfw.timer.newer.*; + +public class EventGroup_Test { + public static final EventGroup group = new EventGroup(90); + public static final Object lock = new Object(); + + public static void main(String[] args) throws Throwable { + ClockThread clock = new ClockThread(); + clock.start(); + clock.add(group, 20); + for (int i = 1; i < 10; i++) { + new ThreadImpl(i).start(); + } + Thread.sleep(1000); + synchronized (lock) { + lock.notifyAll(); + } + Thread.sleep(5000); + clock.close(); + } + + static class ThreadImpl extends Thread { + private int id; + + public ThreadImpl(int id) { + this.id = id; + } + + public void run() { + synchronized (lock) { + try { + lock.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + return; + } + } + for (int i = 1; i < 10; i++) { + group.add(new TimerEventImpl(id, i)); + } + } + } + + static class EventImpl implements Event { + + private int id; + private int num; + private int time = 0; + private long previous = System.currentTimeMillis(); + private int[] log = new int[5]; + + public EventImpl(int id, int num) { + this.id = id; + this.num = num; + } + + public boolean isContinue() { + long now; + System.out.println(now = System.currentTimeMillis()); + log[time++] = (int) (now - previous); + previous = now; + if (time >= 5) { + System.out.println("-------" + id + " " + num + " " + time + + ":" + log[0] + "," + log[1] + "," + log[2] + "," + + log[3] + "," + log[4]); + } + return time < 5; + } + } +} diff --git a/demo/test/Timer_Test.java b/demo/test/Timer_Test.java new file mode 100644 index 0000000..4cd8e96 --- /dev/null +++ b/demo/test/Timer_Test.java @@ -0,0 +1,88 @@ +/** + * Copyright 2011 Huize Dai + * + * This file is part of MFW. + * + * MFW is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MFW is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with MFW. If not, see . + */ +package test; + +import mfw.pool.Mission; +import mfw.timer.newer.*; + +public class Timer_Test { + public static ClockThreadGroup clock = new ClockThreadGroup(3, true); + public static final Object lock = new Object(); + + public static void main(String[] args) throws Throwable { + for (int i = 1; i < 10; i++) { + new MissionImpl(i).start(); + } + Thread.sleep(1000); + synchronized (lock) { + lock.notifyAll(); + } + Thread.sleep(5000); + clock.close(); + } + + static class MissionImpl extends Mission { + private int id; + + public MissionImpl(int id) { + this.id = id; + } + + public void run() { + synchronized (lock) { + try { + lock.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + return; + } + } + for (int i = 1; i < 10; i++) { + clock.add(new TimerEventImpl(id, i), 10 * i); + } + } + } + + static class TimerEventImpl extends TimerEvent { + + private int id; + private int num; + private int time = 0; + private long previous = System.currentTimeMillis(); + private int[] log = new int[5]; + + public TimerEventImpl(int id, int num) { + this.id = id; + this.num = num; + } + + public boolean isContinue() { + long now; + System.out.println(now = System.currentTimeMillis()); + log[time++] = (int) (now - previous); + previous = now; + if (time >= 5) { + System.out.println("-------" + id + " " + num + " " + time + + ":" + log[0] + "," + log[1] + "," + log[2] + "," + + log[3] + "," + log[4]); + } + return time < 5; + } + } +} diff --git a/src/mfw/timer/newer/ClockThread.java b/src/mfw/timer/newer/ClockThread.java new file mode 100755 index 0000000..c87e524 --- /dev/null +++ b/src/mfw/timer/newer/ClockThread.java @@ -0,0 +1,155 @@ +/** + * Copyright 2011 Huize Dai + * + * This file is part of MFW. + * + * MFW is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MFW is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with MFW. If not, see . + */ +package mfw.timer.newer; + +public class ClockThread extends Thread { + private final TimerEvent head; + + public ClockThread() { + this.head = new TimerEvent() { + + public boolean isContinue() { + return true; + } + }; + } + + ClockThread(TimerEvent head) { + this.head = head; + } + + private final Object lock = new Object(); + private TimerEvent current; + private boolean flag = true; + + public void add(TimerEvent event, long diff) { + event.diff = diff; + event.nextTime = System.currentTimeMillis() + diff; + try { + boolean needPut = false; + synchronized (lock) { + if (!_test(event)) { + head.lock(); + needPut = true; + } + } + if (needPut) + _put(event); + } catch (InterruptedException e) { + throw new Error(e); + } + } + + public void close() { + synchronized (lock) { + flag = false; + lock.notify(); + } + } + + private void _put(TimerEvent event) throws InterruptedException { + TimerEvent ptr, swap; + (ptr = head).lock(); + while (true) { + if (ptr.next != null && ptr.next.nextTime < event.nextTime) { + (swap = ptr.next).lock(); + ptr.unlock(); + ptr = swap; + continue; + } + event.next = ptr.next; + ptr.next = event; + break; + } + ptr.unlock(); + } + + private TimerEvent _get() throws InterruptedException { + head.lock(); + TimerEvent swap = head.next; + if (swap != null) { + swap.lock(); + head.next = swap.next; + swap.unlock(); + } + head.unlock(); + return swap; + } + + public void run() { + long now; + try { + synchronized (lock) { + while (flag) { + if (current == null && (current = _get()) == null) { + lock.wait(); + } else if ((now = System.currentTimeMillis()) < current.nextTime) { + lock.wait(current.nextTime - now); + } else { + if (current.isContinue()) { + current.nextTime += current.diff; + _put(current); + } + current = null; + } + } + } + } catch (InterruptedException e) { + throw new Error(e); + } + } + + private boolean _test(TimerEvent event) throws InterruptedException { + synchronized (lock) { + if (current == null) { + current = event; + lock.notify(); + return true; + } else if (current.nextTime > event.nextTime) { + _put(current); + current = event; + lock.notify(); + return true; + } else { + return false; + } + } + } + + static class Lock { + private Thread keyThread = null; + + public synchronized void lock() throws InterruptedException { + Thread current = Thread.currentThread(); + while (keyThread != current) { + if (keyThread == null) + keyThread = current; + else + this.wait(); + } + } + + public synchronized void unlock() { + if (keyThread == Thread.currentThread()) { + keyThread = null; + this.notify(); + } + } + } +} diff --git a/src/mfw/timer/newer/ClockThreadGroup.java b/src/mfw/timer/newer/ClockThreadGroup.java new file mode 100644 index 0000000..3a67f12 --- /dev/null +++ b/src/mfw/timer/newer/ClockThreadGroup.java @@ -0,0 +1,58 @@ +/** + * Copyright 2011 Huize Dai + * + * This file is part of MFW. + * + * MFW is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MFW is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with MFW. If not, see . + */ +package mfw.timer.newer; + +public class ClockThreadGroup { + + private ClockThread[] clockPool; + private int i = 0; + + public ClockThreadGroup(int count, boolean isSeries) { + clockPool = new ClockThread[count]; + if (isSeries) { + TimerEvent event = new TimerEvent() { + + public boolean isContinue() { + return true; + } + }; + for (int i = 0; i < clockPool.length; i++) { + (clockPool[i] = new ClockThread(event)).start(); + } + } else { + for (int i = 0; i < clockPool.length; i++) { + (clockPool[i] = new ClockThread()).start(); + } + } + } + + public void add(TimerEvent event, long diff) { + ClockThread clock; + synchronized (this) { + clock = clockPool[i = (i + 1) % clockPool.length]; + } + clock.add(event, diff); + } + + public void close() { + for (int i = 0; i < clockPool.length; i++) { + clockPool[i].close(); + } + } +} diff --git a/src/mfw/timer/newer/Event.java b/src/mfw/timer/newer/Event.java new file mode 100644 index 0000000..ac87360 --- /dev/null +++ b/src/mfw/timer/newer/Event.java @@ -0,0 +1,23 @@ +/** + * Copyright 2011 Huize Dai + * + * This file is part of MFW. + * + * MFW is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MFW is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with MFW. If not, see . + */ +package mfw.timer.newer; + +public interface Event { + boolean isContinue(); +} diff --git a/src/mfw/timer/newer/EventGroup.java b/src/mfw/timer/newer/EventGroup.java new file mode 100755 index 0000000..4eaaa36 --- /dev/null +++ b/src/mfw/timer/newer/EventGroup.java @@ -0,0 +1,60 @@ +/** + * Copyright 2011 Huize Dai + * + * This file is part of MFW. + * + * MFW is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MFW is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with MFW. If not, see . + */ +package mfw.timer.newer; + +public class EventGroup extends TimerEvent implements Event { + + private final Event[] atoms; + private int ptr = 0; + private boolean isContinue = true; + private final Object lock = new Object(); + + public EventGroup(int len) { + atoms = new Event[len]; + } + + public boolean add(Event event) { + synchronized (lock) { + if (ptr < atoms.length) { + atoms[ptr++] = event; + return true; + } else { + return false; + } + } + } + + public void close() { + isContinue = false; + } + + public boolean isContinue() { + for (int i = 0; i < ptr;) { + if (!atoms[i].isContinue()) { + synchronized (lock) { + atoms[i] = atoms[--ptr]; + } + } else { + i++; + } + } + return isContinue; + } + +} diff --git a/src/mfw/timer/newer/TimerEvent.java b/src/mfw/timer/newer/TimerEvent.java new file mode 100755 index 0000000..a66d97e --- /dev/null +++ b/src/mfw/timer/newer/TimerEvent.java @@ -0,0 +1,28 @@ +/** + * Copyright 2011 Huize Dai + * + * This file is part of MFW. + * + * MFW is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MFW is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with MFW. If not, see . + */ +package mfw.timer.newer; + +public abstract class TimerEvent extends ClockThread.Lock implements Event { + TimerEvent next; + + long nextTime; + long diff; + + public abstract boolean isContinue(); +} -- 2.11.4.GIT