Tricks of the Java Programming Gurus
by Glenn L. Vanderburg. et al.
1.Applet间的通讯(2)
相互查找
使用静态变量进行通讯并不意味着applet就可以同时被初始化。不同的实例还是先后启动的,我们并不能保证它们的启动次序。然而,有一点我们可以确定:在第一个ColorRelay applet实例被创建之前,类ColorRelay已经初始化了,因此,当所有applet实例启动时,它们都将获得类的静态变量。
但是,当你使用静态变量时必须小心,因为多个实例可能同时访问静态变量。为了解决这个问题,我使用了两个同步方法(synchronized methods)从链表中增减applet实例。因为它们是synchronized static方法,当它们运行时,ColorRelay 类会被索住,以避免并发访问。清单1.3是这两个方法的代码。值得注意的是,当第一个元素被加到链表之后,主控线程(controller thread)将启动。我们随后会看到当最后一个元素从链表中被移出后,这个线程将自动停止。
清单 1.3. ColorRelay.java (part 2).
/** * Adds an instance to the list of active instances maintained in the * class. No check is made to prevent adding the same instance twice. * @param elem the ColorRelay instance to add to the list. * @see #removeFromList */ static synchronized void addToList(ColorRelay elem) { if (list == null) { list = listTail = elem; elem.next = elem.prev = null;
// Because the list has elements now, we should start the thread. relayer = new Thread(new ColorRelay()); relayer.start(); } else { elem.prev = listTail; listTail.next = listTail = elem; elem.next = null; } }
/** * Removes an instance from the list of active instances maintained in * the class. Works properly but does <em>not</em> signal an error if * the element was not actually on the list. * @param elem the ColorRelay instance to be removed from the list. * @see #addToList */ static synchronized void removeFromList(ColorRelay elem) { ColorRelay curr = list; while (curr != null && curr != elem) { curr = curr.next; }
if (curr == elem) { // We found it! if (list == curr) { list = curr.next; } if (listTail == curr) { listTail = curr.prev; } if (curr.next != null) { curr.next.prev = curr.prev; } if (curr.prev != null) { curr.prev.next = curr.next; } curr.next = curr.prev = null; } // If curr is null, then the element is not on the list // at all. We could treat that as an error, but I'm // choosing to report success.
return; }
初始化共享数据
Applet被创建之后init方法被调用,这个方法检查、转换和存储applet的参数。对image参数需要额外的注意,因为它是存储在另一个静态变量中的。在试图访问originalImage静态变量之前,要锁住ColorRelay类,我们没有使用synchronized 方法,而是使用一段synchronized 监测语句来实现这个目的。(事实上,应该只有一个ColorRelay实例获得image参数,但为了防止HTML中的编码错误,我们采取了上述的预防措施)。清单1.4是init的代码。
清单 1.4. ColorRelay.java (part 3).
/** * Initializes the applet instance. Checks and stores * parameters and initializes other instance variables. */ public void init() { String flash = getParameter("flashColor"); if (flash != null) { try { flashColor = new Color(parseRGB(flash)); } catch (NumberFormatException e) { // Ignore a bad parameter and just go with the default. } }
String sleep = getParameter("sleepTime"); if (sleep != null) { try { sleepSecs = Integer.parseInt(sleep); } catch (NumberFormatException e) { // Ignore a bad parameter and just go with the default. } } String imageURL = getParameter("image"); if (imageURL != null) { Class cr = Class.forName("COM.MCP.Samsnet.tjg.ColorRelay"); synchronized (cr) { if (originalImage == null) { originalImage = getImage(getDocumentBase(), imageURL); } } }
tracker = new MediaTracker(this); }
Working Together
当浏览器准备执行applet时,start 方法被调用,将applet加入链表。在stop方法中,applet被译出链表。在前面的代码中你已经看到,第一个链表元素的添加将导致控制线程的启动。这个控制线程仅仅是循环读取链表元素,一次将链表中的某个元素点亮(显示彩色图片)。至于显示的持续时间,是由applet自己决定的。如果链表中没有元素了,控制线程自动终止。清单1.5是控制线程的strat、stop以及run方法。
清单 1.5. ColorRelay.java (part 4).
/** * Starts the applet running. The ColorRelay hooks up with * other instances on the same page and begins coordinating * when this method is called. */ public void start() { // Ordinarily, we want to display the original image. image = originalImage;
ColorRelay.addToList(this); // Let's get to work! }
/** * Stops the applet. The ColorRelay instance removes itself from the * group of cooperating applets when this method is called. */ public void stop() { ColorRelay.removeFromList(this); }
/** * Loops through the list of active instances for as long as it is * non-empty, calling each instance's 'flash' method. * @see #flash */ public void run () { ColorRelay curr;
// Continue running through the list until it's empty ... while (list != null) { for (curr = list; curr != null; curr = curr.next) { try { curr.flash(); } catch (InterruptedException e) { } } } }
翻译:chenyuan_tongji ([email protected])
|