当前位置: 技术问答>java相关
请高手帮我编译一下这个文件,50分相谢!!
来源: 互联网 发布时间:2015-01-04
本文导语: 我用jBuilder4居然不能编译这个java文件,求高手指教........ /*源程序清单5-22*/ import java.net.*; import java.awt.*; import java.awt.event.*; import java.applet.*; import javax.swing.*; import com.borland.jbcl.layout.*; import java.io.*; import java.util.*...
我用jBuilder4居然不能编译这个java文件,求高手指教........
/*源程序清单5-22*/
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import javax.swing.*;
import com.borland.jbcl.layout.*;
import java.io.*;
import java.util.*;
public class TalkApplet extends JApplet implements Runnable
{
boolean isStandalone = false;
Label userInfo = new Label();
TextField userText = new TextField();
Label label1 = new Label();
TextArea messageText = new TextArea();
Button sendButton = new Button();
java.awt.List userList = new java.awt.List();
URL chatURL;
URLConnection connect;
//用于标识用户是否登录
boolean loggedin=false;
String username;
Thread pollThread=null;
PaneLayout paneLayout1 = new PaneLayout();
/**Get a parameter value*/
public String getParameter(String key, String def)
{
return isStandalone ? System.getProperty(key, def) :
(getParameter(key) != null ? getParameter(key) : def);
}
/**Construct the applet*/
public TalkApplet()
{
}
/**Initialize the applet*/
public void init()
{
try
{
jbInit();
}
catch(Exception e)
{
e.printStackTrace();
}
}
/**Component initialization*/
private void jbInit() throws Exception {
if(pollThread!=null)
return;
userInfo.setText("请输入用户名(请不要超过10个字符):");
this.setSize(new Dimension(400,300));
this.getContentPane().setLayout(paneLayout1);
label1.setText("聊天内容:");
messageText.setEditable(false);
sendButton.setLabel("发送");
sendButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
sendButton_actionPerformed(e);
}
});
userText.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
userText_actionPerformed(e);
}
});
this.getContentPane().add(userInfo, new PaneConstraints("userInfo", "userInfo", PaneConstraints.ROOT, 1.0f));
this.getContentPane().add(userText, new PaneConstraints("userText", "userInfo", PaneConstraints.BOTTOM, 0.9166667f));
this.getContentPane().add(messageText, new PaneConstraints("messageText", "userText", PaneConstraints.BOTTOM, 0.90181816f));
this.getContentPane().add(userList, new PaneConstraints("userList", "messageText", PaneConstraints.TOP, 0.24193548f));
this.getContentPane().add(sendButton, new PaneConstraints("sendButton", "userList", PaneConstraints.LEFT, 0.6125f));
this.getContentPane().add(label1, new PaneConstraints("label1", "sendButton", PaneConstraints.BOTTOM, 0.6f));
chatURL=getCodeBase();
int currPriority=Thread.currentThread().getPriority();
int newPriority=currPriority==Thread.MIN_PRIORITY?Thread.MIN_PRIORITY:currPriority-1;
pollThread=new Thread(this,"talkPoll");
pollThread.setDaemon(true);
pollThread.setPriority(newPriority);
pollThread.start();
}
/**Get Applet information*/
public String getAppletInfo()
{
return "Applet Information";
}
/**Get parameter info*/
public String[][] getParameterInfo()
{
return null;
}
public synchronized void start()
{
if(!isLoggedin()&&username!=null)
login();
if(pollThread!=null&&pollThread.isAlive())
{
pollThread.resume();
}
else
{
pollThread=new Thread(this,"talkPoll");
pollThread.setDaemon(true);
pollThread.start();
}
}
//当Applet在浏览器中不可见时,就挂起线程pollthread,并退出"聊天室"
public synchronized void stop()
{
if (pollThread.isAlive())
{
pollThread.suspend();
}
logout();
}
public synchronized void destroy()
{
if (pollThread != null && pollThread.isAlive())
{
pollThread.stop();
pollThread = null;
}
logout();
}
//每隔3秒从服务器中取别的用户输入的信息和加入聊天室的用户
public void run()
{
while (!Thread.interrupted())
{
//若用户已经登陆,则不时的取回别的用户输入的信息
//和机如的的用户名
if (isLoggedin())
{
pollList();
poll();
}
//若没有用户登陆,则取回正在聊天室中的用户
else
{
pollList();
}
try
{
//睡眠3秒钟
Thread.sleep(1000*3);
}
catch (InterruptedException e)
{
}
}
}
//登陆到服务器
private void login()
{
if (username ==null) return;
String queryString = "chatservlet?mode=login&user="+URLEncoder.encode(username);
//与服务器通信
try
{
connect = (new URL(/tech-qa-java/chatURL,queryString/index.html)).openConnection();
connect.setDefaultUseCaches(false);
connect.setUseCaches(false);
connect.setDoInput(true);
connect.setDoOutput(false);
connect.connect();
DataInputStream in = new DataInputStream(connect.getInputStream());
String response = in.readLine();
if (response.startsWith("+"))
{
//标识用户已经登陆
setLoggedin(true);
showStatus("登录用户名:" + username);
//提示用户输入信息
userInfo.setText("请输入你需要发送的信息:");
repaint();
}
else
{
showStatus("Error logging in " + response);
System.err.println("Error logging in " + response);
}
}
catch (MalformedURLException e2)
{
System.err.println("MalformedURLException logging in!");
e2.printStackTrace(System.err);
showStatus("Error logging in!");
}
catch (IOException e1)
{
System.err.println("IOException logging in!");
e1.printStackTrace(System.err);
showStatus("Error logging in!");
}
}
//退出聊天室
private void logout()
{
if (!isLoggedin() || username ==null)
{
return;
}
String queryString = "chatservlet?mode=logout&username=" +URLEncoder.encode(username);
//与服务器通信
try
{
connect = (new URL(/tech-qa-java/chatURL,queryString/index.html)).openConnection();
connect.setUseCaches(false);
connect.setDoInput(true);
connect.setDoOutput(false);
connect.connect();
DataInputStream in = new DataInputStream(connect.getInputStream());
String response = in.readLine();
if (response.startsWith("+"))
{
//标识用户已经退出聊天室
setLoggedin(false);
showStatus(username + "离开聊天室!");
}
else
{
showStatus("Error logging out" + response);
System.err.println("Error logging out" + response);
}
}
catch (MalformedURLException e2)
{
System.err.println("MalformedURLException logging out!");
e2.printStackTrace(System.err);
showStatus("Error logging out!");
}
catch (IOException e1)
{
System.err.println("IOException logging out!");
e1.printStackTrace(System.err);
showStatus("Error logging out!");
}
}
//发送用户输入的信息
private void send()
{
String message = userText.getText();
//用户输入空字符串不发送
if (message.equals(""))
{
return;
}
//清除用户在Applet中输入的内容
userText.setText("");
showStatus("发送信息!");
String queryString = "chatservlet?mode=send&user="+URLEncoder.encode(username);
queryString = queryString + "&message="+URLEncoder.encode(message);
try
{
connect = (new URL(/tech-qa-java/chatURL,queryString/index.html)).openConnection();
connect.setUseCaches(false);
connect.setDoInput(true);
connect.setDoOutput(false);
connect.connect();
DataInputStream in = new DataInputStream(connect.getInputStream());
String response = in.readLine();
if (response.startsWith("+"))
{
showStatus("信息发送出去了");
}
else
{
showStatus("发送信息错误 " + response);
System.err.println("Error sending message " + response);
}
}
catch (MalformedURLException e2)
{
System.err.println("MalformedURLException logging in!");
e2.printStackTrace(System.err);
showStatus("Error logging in!");
}
catch (IOException e1)
{
System.err.println("IOException logging in!");
e1.printStackTrace(System.err);
showStatus("Error logging in!");
}
}
//返回所有用户输入的信息
private void poll()
{
String queryString = "chatservlet?mode=poll&user=" +URLEncoder.encode(username);
try
{
DataInputStream in = new DataInputStream(
new URL(/tech-qa-java/chatURL,queryString/index.html).openStream());
String nextLine = in.readLine();
if (!nextLine.startsWith("+"))
{
showStatus("Error getting messages from server!");
System.err.println("Error getting messages from server!");
return;
}
nextLine = in.readLine();
while (nextLine != null && !nextLine.equals("."))
{
System.err.println(nextLine);
messageText.appendText(nextLine + "rn");
repaint();
nextLine = in.readLine();
}
}
catch (IOException e)
{
System.err.println("IOException poll!");
e.printStackTrace(System.err);
}
}
//返回正在聊天室中的用户
private void pollList()
{
String queryString = "chatservlet?mode=list";
Vector users = new Vector();
try
{
URL listURL = new URL(/tech-qa-java/chatURL,queryString/index.html);
URLConnection listConn = listURL.openConnection();
listConn.setDefaultUseCaches(false);
listConn.setUseCaches(false);
listConn.connect();
DataInputStream in = new DataInputStream(
listConn.getInputStream());
String nextLine = in.readLine();
if (!nextLine.startsWith("+"))
{
showStatus("Error getting userlist from server!");
return;
}
nextLine = in.readLine();
while (nextLine != null && !nextLine.equals("."))
{
users.addElement(nextLine);
nextLine = in.readLine();
}
//清除旧的用户表,加入新的
if (!users.isEmpty())
{
userList.clear();
int size = users.size();
for (int I=0;I10)
{
showStatus("请不要超过10个字符!");
}
else
{
userText.setText("");
login();
}
}
}
void userText_actionPerformed(ActionEvent e)
{
sendText();
}
}
/*源程序清单5-22*/
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import javax.swing.*;
import com.borland.jbcl.layout.*;
import java.io.*;
import java.util.*;
public class TalkApplet extends JApplet implements Runnable
{
boolean isStandalone = false;
Label userInfo = new Label();
TextField userText = new TextField();
Label label1 = new Label();
TextArea messageText = new TextArea();
Button sendButton = new Button();
java.awt.List userList = new java.awt.List();
URL chatURL;
URLConnection connect;
//用于标识用户是否登录
boolean loggedin=false;
String username;
Thread pollThread=null;
PaneLayout paneLayout1 = new PaneLayout();
/**Get a parameter value*/
public String getParameter(String key, String def)
{
return isStandalone ? System.getProperty(key, def) :
(getParameter(key) != null ? getParameter(key) : def);
}
/**Construct the applet*/
public TalkApplet()
{
}
/**Initialize the applet*/
public void init()
{
try
{
jbInit();
}
catch(Exception e)
{
e.printStackTrace();
}
}
/**Component initialization*/
private void jbInit() throws Exception {
if(pollThread!=null)
return;
userInfo.setText("请输入用户名(请不要超过10个字符):");
this.setSize(new Dimension(400,300));
this.getContentPane().setLayout(paneLayout1);
label1.setText("聊天内容:");
messageText.setEditable(false);
sendButton.setLabel("发送");
sendButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
sendButton_actionPerformed(e);
}
});
userText.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
userText_actionPerformed(e);
}
});
this.getContentPane().add(userInfo, new PaneConstraints("userInfo", "userInfo", PaneConstraints.ROOT, 1.0f));
this.getContentPane().add(userText, new PaneConstraints("userText", "userInfo", PaneConstraints.BOTTOM, 0.9166667f));
this.getContentPane().add(messageText, new PaneConstraints("messageText", "userText", PaneConstraints.BOTTOM, 0.90181816f));
this.getContentPane().add(userList, new PaneConstraints("userList", "messageText", PaneConstraints.TOP, 0.24193548f));
this.getContentPane().add(sendButton, new PaneConstraints("sendButton", "userList", PaneConstraints.LEFT, 0.6125f));
this.getContentPane().add(label1, new PaneConstraints("label1", "sendButton", PaneConstraints.BOTTOM, 0.6f));
chatURL=getCodeBase();
int currPriority=Thread.currentThread().getPriority();
int newPriority=currPriority==Thread.MIN_PRIORITY?Thread.MIN_PRIORITY:currPriority-1;
pollThread=new Thread(this,"talkPoll");
pollThread.setDaemon(true);
pollThread.setPriority(newPriority);
pollThread.start();
}
/**Get Applet information*/
public String getAppletInfo()
{
return "Applet Information";
}
/**Get parameter info*/
public String[][] getParameterInfo()
{
return null;
}
public synchronized void start()
{
if(!isLoggedin()&&username!=null)
login();
if(pollThread!=null&&pollThread.isAlive())
{
pollThread.resume();
}
else
{
pollThread=new Thread(this,"talkPoll");
pollThread.setDaemon(true);
pollThread.start();
}
}
//当Applet在浏览器中不可见时,就挂起线程pollthread,并退出"聊天室"
public synchronized void stop()
{
if (pollThread.isAlive())
{
pollThread.suspend();
}
logout();
}
public synchronized void destroy()
{
if (pollThread != null && pollThread.isAlive())
{
pollThread.stop();
pollThread = null;
}
logout();
}
//每隔3秒从服务器中取别的用户输入的信息和加入聊天室的用户
public void run()
{
while (!Thread.interrupted())
{
//若用户已经登陆,则不时的取回别的用户输入的信息
//和机如的的用户名
if (isLoggedin())
{
pollList();
poll();
}
//若没有用户登陆,则取回正在聊天室中的用户
else
{
pollList();
}
try
{
//睡眠3秒钟
Thread.sleep(1000*3);
}
catch (InterruptedException e)
{
}
}
}
//登陆到服务器
private void login()
{
if (username ==null) return;
String queryString = "chatservlet?mode=login&user="+URLEncoder.encode(username);
//与服务器通信
try
{
connect = (new URL(/tech-qa-java/chatURL,queryString/index.html)).openConnection();
connect.setDefaultUseCaches(false);
connect.setUseCaches(false);
connect.setDoInput(true);
connect.setDoOutput(false);
connect.connect();
DataInputStream in = new DataInputStream(connect.getInputStream());
String response = in.readLine();
if (response.startsWith("+"))
{
//标识用户已经登陆
setLoggedin(true);
showStatus("登录用户名:" + username);
//提示用户输入信息
userInfo.setText("请输入你需要发送的信息:");
repaint();
}
else
{
showStatus("Error logging in " + response);
System.err.println("Error logging in " + response);
}
}
catch (MalformedURLException e2)
{
System.err.println("MalformedURLException logging in!");
e2.printStackTrace(System.err);
showStatus("Error logging in!");
}
catch (IOException e1)
{
System.err.println("IOException logging in!");
e1.printStackTrace(System.err);
showStatus("Error logging in!");
}
}
//退出聊天室
private void logout()
{
if (!isLoggedin() || username ==null)
{
return;
}
String queryString = "chatservlet?mode=logout&username=" +URLEncoder.encode(username);
//与服务器通信
try
{
connect = (new URL(/tech-qa-java/chatURL,queryString/index.html)).openConnection();
connect.setUseCaches(false);
connect.setDoInput(true);
connect.setDoOutput(false);
connect.connect();
DataInputStream in = new DataInputStream(connect.getInputStream());
String response = in.readLine();
if (response.startsWith("+"))
{
//标识用户已经退出聊天室
setLoggedin(false);
showStatus(username + "离开聊天室!");
}
else
{
showStatus("Error logging out" + response);
System.err.println("Error logging out" + response);
}
}
catch (MalformedURLException e2)
{
System.err.println("MalformedURLException logging out!");
e2.printStackTrace(System.err);
showStatus("Error logging out!");
}
catch (IOException e1)
{
System.err.println("IOException logging out!");
e1.printStackTrace(System.err);
showStatus("Error logging out!");
}
}
//发送用户输入的信息
private void send()
{
String message = userText.getText();
//用户输入空字符串不发送
if (message.equals(""))
{
return;
}
//清除用户在Applet中输入的内容
userText.setText("");
showStatus("发送信息!");
String queryString = "chatservlet?mode=send&user="+URLEncoder.encode(username);
queryString = queryString + "&message="+URLEncoder.encode(message);
try
{
connect = (new URL(/tech-qa-java/chatURL,queryString/index.html)).openConnection();
connect.setUseCaches(false);
connect.setDoInput(true);
connect.setDoOutput(false);
connect.connect();
DataInputStream in = new DataInputStream(connect.getInputStream());
String response = in.readLine();
if (response.startsWith("+"))
{
showStatus("信息发送出去了");
}
else
{
showStatus("发送信息错误 " + response);
System.err.println("Error sending message " + response);
}
}
catch (MalformedURLException e2)
{
System.err.println("MalformedURLException logging in!");
e2.printStackTrace(System.err);
showStatus("Error logging in!");
}
catch (IOException e1)
{
System.err.println("IOException logging in!");
e1.printStackTrace(System.err);
showStatus("Error logging in!");
}
}
//返回所有用户输入的信息
private void poll()
{
String queryString = "chatservlet?mode=poll&user=" +URLEncoder.encode(username);
try
{
DataInputStream in = new DataInputStream(
new URL(/tech-qa-java/chatURL,queryString/index.html).openStream());
String nextLine = in.readLine();
if (!nextLine.startsWith("+"))
{
showStatus("Error getting messages from server!");
System.err.println("Error getting messages from server!");
return;
}
nextLine = in.readLine();
while (nextLine != null && !nextLine.equals("."))
{
System.err.println(nextLine);
messageText.appendText(nextLine + "rn");
repaint();
nextLine = in.readLine();
}
}
catch (IOException e)
{
System.err.println("IOException poll!");
e.printStackTrace(System.err);
}
}
//返回正在聊天室中的用户
private void pollList()
{
String queryString = "chatservlet?mode=list";
Vector users = new Vector();
try
{
URL listURL = new URL(/tech-qa-java/chatURL,queryString/index.html);
URLConnection listConn = listURL.openConnection();
listConn.setDefaultUseCaches(false);
listConn.setUseCaches(false);
listConn.connect();
DataInputStream in = new DataInputStream(
listConn.getInputStream());
String nextLine = in.readLine();
if (!nextLine.startsWith("+"))
{
showStatus("Error getting userlist from server!");
return;
}
nextLine = in.readLine();
while (nextLine != null && !nextLine.equals("."))
{
users.addElement(nextLine);
nextLine = in.readLine();
}
//清除旧的用户表,加入新的
if (!users.isEmpty())
{
userList.clear();
int size = users.size();
for (int I=0;I10)
{
showStatus("请不要超过10个字符!");
}
else
{
userText.setText("");
login();
}
}
}
void userText_actionPerformed(ActionEvent e)
{
sendText();
}
}
|
错是没有错,从jdk1.2开始就对jdk1.1以前使用的一些事件进行了替换,尽管以前的某些事件仍可用,但会被报出warning,就象这句"TalkApplet.java": Warning #: 368 : method resume() in class java.lang.Thread has been deprecated at line 102, column 18
是说resume()事件已经不被推荐使用,类似的有Thread.stop、Thread.suspend.粘贴过来一篇文章,看了会有用的:
为什么不鼓励使用 Thread.stop、Thread.suspend和 Thread.resume?
--------------------------------------------------------------------------------
为什么不鼓励使用 Thread.stop?
因为它本质上就是不安全的。停止线程会导致解锁它已锁定的所有监视程序(ThreadDeath 异常传播到栈上后即解锁监视程序)。如果这些监视程序前面保护的任何对象处于不一致状态,则其它线程即可能将这些对象视为处于不一致状态。我们将这种对象称为损坏的对象。当线程操作损坏的对象时,可能会产生任何意外的行为。这种行为可能很难觉察,也可能非常明显。与其它未检查的异常不同,ThreadDeath 将悄悄杀掉线程;这样,用户就不会得到其程序已被破坏的警告。这种破坏可能会在实际损坏发生之后的任何时间显示出来,甚至可能会在数小时或数天之后。
--------------------------------------------------------------------------------
难道不能捕获 ThreadDeath 异常并修复被损坏的对象?
从理论上是可行的,但编写正确的多线程代码的任务将会相当复杂。该任务几乎是无法完成的,原因如下:
线程可能会在几乎任何地方抛出 ThreadDeath 异常。所以必须在此基础上对所有的同步方法和块进行研究。
线程可能会在清除第一个 ThreadDeath 异常(在 catch 或 finally 子句中)时抛出第二个异常。 因此必须重复清除直到它成功完成。实现这一点的代码将相当复杂。
总之,上述意图是不切实际的。
--------------------------------------------------------------------------------
对于 Thread.stop(Throwable) 又该怎样办?
除了上述所有问题之外,该方法还可能用来产生其目标线程尚不能处理的异常(包括离开该方法线程几乎不可能产生的已检查异常)。例如,下列方法的行为等同于 Java 的 throw 操作,但是绕过了编译器的下列尝试:即保证调用方法已经声明了它可能抛出的所有已检查异常:
static void sneakyThrow(Throwable t) {
Thread.currentThread().stop(t);
}
--------------------------------------------------------------------------------
应该用什么来代替 Thread.stop?
大多数使用 stop 的情况都应该用简单修改一些变量以指示目标线程应停止运行的代码所代替。目标线程应该定期检查该变量,并在该变量指示需要它停止运行时以一种合理的方法从其 run 方法中返回(这是 JavaSoft 教程始终推荐的方法)。要确保停止请求的即时通讯,该变量必须是 volatile(迅变)的(或对该变量的访问必须是同步的)。
例如,假定 applet 包含下列 start、stop 和 run 方法:
private Thread blinker;
public void start() {
blinker = new Thread(this);
blinker.start();
}
public void stop() {
blinker.stop(); // 不安全!
}
public void run() {
Thread thisThread = Thread.currentThread();
while (true) {
try {
thisThread.sleep(interval);
} catch (InterruptedException e){
}
repaint();
}
}
则可以通过用下列内容替代 applet 的 stop 和 run 方法来避免使用 Thread.stop:
private volatile Thread blinker;
public void stop() {
blinker = null;
}
public void run() {
Thread thisThread = Thread.currentThread();
while (blinker == thisThread) {
try {
thisThread.sleep(interval);
} catch (InterruptedException e){
}
repaint();
}
}
--------------------------------------------------------------------------------
如何停止已经等待了很长时间(例如等待输入)的线程?
这就是 Thread.interrupt 方法的用途所在。用户可以使用上述“基于状态”的信号机制,但状态改变(前例中为 blinker = null)的后面可以跟 Thread.interrupt 调用以中断等待:
public void stop() {
Thread moribund = waiter;
waiter = null;
moribund.interrupt();
}
要使用这种技术,关键是任何捕获中断异常并无法立即处理它的方法要重新声明该异常。之所以称为重新声明而不是重抛出,是因为该异常不是总可以重新抛出的。如果捕获 InterruptedException 异常的方法没有声明抛出该(已检查的)异常,则它应该用下列代码“重新中断自己”:
Thread.currentThread().interrupt();
这可以确保 Thread 尽快重新产生 InterruptedException 异常。
--------------------------------------------------------------------------------
如果线程不响应 Thread.interrupt 该怎么办?
有些情况下,可以使用应用程序特定技巧。例如,如果线程在等待已知套接字,则可以关闭该套接字以使线程立即返回。不幸地是,目前尚没有通用的技术。应该说明,对于所有等待线程不响应 Thread.interrupt 的情况,它也不会响应 Thread.stop。 这种情况包括故意的拒绝服务攻击和 thread.stop 与 thread.interrupt 不能正常工作的 I/O 操作。
--------------------------------------------------------------------------------
为什么不鼓励使用 Thread.suspend 和 Thread.resume?
Thread.suspend 从本质上就是易于死锁的。如果目标线程锁定在一个监视程序上,从而在关键系统资源挂起时保护资源,则在目标线程恢复前将没有线程能访问该资源。如果试图恢复目标线程的线程在调用 resume 之前试图锁定该监视程序,即出现死锁。这种死锁通常将自己显示为“冻结”进程。
--------------------------------------------------------------------------------
应该使用什么来代替 Thread.suspend 和 Thread.resume?
与 Thread.stop 一样,最谨慎的方法是让“目标”线程轮询一个指示所需线程状态(活动或挂起)的变量。当需要挂起状态时,线程将使用 Object.wait 进行等待。当线程恢复时,将使用 Object.notify 通知目标线程。
例如,假定 applet 包含下列 mousePressed 事件处理程序,它将触发名为 blinker 的线程的状态:
private boolean threadSuspended;
Public void mousePressed(MouseEvent e) {
e.consume();
if (threadSuspended)
blinker.resume();
else
blinker.suspend(); // 易于死锁!
threadSuspended = !threadSuspended;
}
用下列代码替代上述事件处理程序,即可避免使用 Thread.suspend 和 Thread.resume:
public synchronized void mousePressed(MouseEvent e) {
e.consume();
threadSuspended = !threadSuspended;
if (!threadSuspended)
notify();
}
然后将下列代码添加到“run loop”中:
synchronized(this) {
while (threadSuspended)
wait();
}
wait 方法将抛出 InterruptedException 异常,因此它必须位于 try ... catch 子句内。最好是将它插入到与 sleep 相同的子句中。sleep 后面(而不是前面)应该进行检查,以在线程“恢复”时立即重绘窗口。最终的 run 方法如下所示:
public void run() {
while (true) {
try {
Thread.currentThread().sleep(interval);
synchronized(this) {
while (threadSuspended)
wait();
}
} catch (InterruptedException e){
}
repaint();
}
}
注意:mousePressed 方法中的 notify 和 run 方法中的 wait 位于 synchronized 块内部。这是语言所要求的,可确保 wait 和 notify 的序列化。从实际应用来说,这消除了导致“挂起”线程丢失 notify 并无限期地保持挂起状态的竞争情况。
尽管 Java 中同步的费用随着平台的成熟不断下降,但它永远不会是免费的。用户可以使用一种简易技巧来删除添加在每一次“run loop”中的同步。前面添加的同步块被一段稍复杂的代码所替代(这段代码只有在实际挂起时才进入同步块):
if (threadSuspended) {
synchronized(this) {
while (threadSuspended)
wait();
}
}
最终的 run 方法为:
public void run() {
while (true) {
try {
Thread.currentThread().sleep(interval);
if (threadSuspended) {
synchronized(this) {
while (threadSuspended)
wait();
}
}
} catch (InterruptedException e){
}
repaint();
}
}
在没有提供显式同步前,threadSuspended 必须为 volatile,以确保挂起请求的快速通讯。
--------------------------------------------------------------------------------
是否可以利用这两种技术产生能安全“停止”或“挂起”的线程?
是,这一点显而易见。但要注意的一个细节是:目标线程可能在另一个线程试图停止它时就已经挂起。如果 stop 方法仅将状态变量 (blinker) 设置为 null,则目标线程将仍然挂起(在监视程序上等待),而不是象它所应该的那样悄悄退出。如果该 applet 被重新启动,则最终可能会出现多个线程在监视程序上等待,从而导致错误行为。
为了解决该问题,stop 方法必须确保目标线程能在挂起时立即恢复。一旦目标线程恢复后,它必须立即识别出自己已被停止并悄悄退出。下面是最终的 run 和 stop 方法:
public void run() {
Thread thisThread = Thread.currentThread();
while (blinker == thisThread) {
try {
thisThread.sleep(interval);
synchronized(this) {
while (threadSuspended && blinker==thisThread)
wait();
}
} catch (InterruptedException e){
}
repaint();
}
}
public synchronized void stop() {
blinker = null;
notify();
}
如果 stop 方法调用 Thread.interrupt(如前所述),则它不必调用 notify,但仍必须实现同步。这可以确保目标线程不会因为偶然情况错过中断。
--------------------------------------------------------------------------------
对于 Thread.destroy 又该怎么办?
Thread.destroy 从来就没有实现。如果它已经实现,则将易于出现 Thread.suspend 方式的死锁(实际上,它大致等价于 Thread.suspend 而没有后续的 Thread.resume)。我们现在还没有实现它,同时也不鼓励使用它(防止将来实现它)。尽管它易于死锁,但在有些情况下程序宁愿冒死锁危险也不愿立即退出。
还有很多waring,也没法一一说,你就去看相应的jdk1.2的文档吧
是说resume()事件已经不被推荐使用,类似的有Thread.stop、Thread.suspend.粘贴过来一篇文章,看了会有用的:
为什么不鼓励使用 Thread.stop、Thread.suspend和 Thread.resume?
--------------------------------------------------------------------------------
为什么不鼓励使用 Thread.stop?
因为它本质上就是不安全的。停止线程会导致解锁它已锁定的所有监视程序(ThreadDeath 异常传播到栈上后即解锁监视程序)。如果这些监视程序前面保护的任何对象处于不一致状态,则其它线程即可能将这些对象视为处于不一致状态。我们将这种对象称为损坏的对象。当线程操作损坏的对象时,可能会产生任何意外的行为。这种行为可能很难觉察,也可能非常明显。与其它未检查的异常不同,ThreadDeath 将悄悄杀掉线程;这样,用户就不会得到其程序已被破坏的警告。这种破坏可能会在实际损坏发生之后的任何时间显示出来,甚至可能会在数小时或数天之后。
--------------------------------------------------------------------------------
难道不能捕获 ThreadDeath 异常并修复被损坏的对象?
从理论上是可行的,但编写正确的多线程代码的任务将会相当复杂。该任务几乎是无法完成的,原因如下:
线程可能会在几乎任何地方抛出 ThreadDeath 异常。所以必须在此基础上对所有的同步方法和块进行研究。
线程可能会在清除第一个 ThreadDeath 异常(在 catch 或 finally 子句中)时抛出第二个异常。 因此必须重复清除直到它成功完成。实现这一点的代码将相当复杂。
总之,上述意图是不切实际的。
--------------------------------------------------------------------------------
对于 Thread.stop(Throwable) 又该怎样办?
除了上述所有问题之外,该方法还可能用来产生其目标线程尚不能处理的异常(包括离开该方法线程几乎不可能产生的已检查异常)。例如,下列方法的行为等同于 Java 的 throw 操作,但是绕过了编译器的下列尝试:即保证调用方法已经声明了它可能抛出的所有已检查异常:
static void sneakyThrow(Throwable t) {
Thread.currentThread().stop(t);
}
--------------------------------------------------------------------------------
应该用什么来代替 Thread.stop?
大多数使用 stop 的情况都应该用简单修改一些变量以指示目标线程应停止运行的代码所代替。目标线程应该定期检查该变量,并在该变量指示需要它停止运行时以一种合理的方法从其 run 方法中返回(这是 JavaSoft 教程始终推荐的方法)。要确保停止请求的即时通讯,该变量必须是 volatile(迅变)的(或对该变量的访问必须是同步的)。
例如,假定 applet 包含下列 start、stop 和 run 方法:
private Thread blinker;
public void start() {
blinker = new Thread(this);
blinker.start();
}
public void stop() {
blinker.stop(); // 不安全!
}
public void run() {
Thread thisThread = Thread.currentThread();
while (true) {
try {
thisThread.sleep(interval);
} catch (InterruptedException e){
}
repaint();
}
}
则可以通过用下列内容替代 applet 的 stop 和 run 方法来避免使用 Thread.stop:
private volatile Thread blinker;
public void stop() {
blinker = null;
}
public void run() {
Thread thisThread = Thread.currentThread();
while (blinker == thisThread) {
try {
thisThread.sleep(interval);
} catch (InterruptedException e){
}
repaint();
}
}
--------------------------------------------------------------------------------
如何停止已经等待了很长时间(例如等待输入)的线程?
这就是 Thread.interrupt 方法的用途所在。用户可以使用上述“基于状态”的信号机制,但状态改变(前例中为 blinker = null)的后面可以跟 Thread.interrupt 调用以中断等待:
public void stop() {
Thread moribund = waiter;
waiter = null;
moribund.interrupt();
}
要使用这种技术,关键是任何捕获中断异常并无法立即处理它的方法要重新声明该异常。之所以称为重新声明而不是重抛出,是因为该异常不是总可以重新抛出的。如果捕获 InterruptedException 异常的方法没有声明抛出该(已检查的)异常,则它应该用下列代码“重新中断自己”:
Thread.currentThread().interrupt();
这可以确保 Thread 尽快重新产生 InterruptedException 异常。
--------------------------------------------------------------------------------
如果线程不响应 Thread.interrupt 该怎么办?
有些情况下,可以使用应用程序特定技巧。例如,如果线程在等待已知套接字,则可以关闭该套接字以使线程立即返回。不幸地是,目前尚没有通用的技术。应该说明,对于所有等待线程不响应 Thread.interrupt 的情况,它也不会响应 Thread.stop。 这种情况包括故意的拒绝服务攻击和 thread.stop 与 thread.interrupt 不能正常工作的 I/O 操作。
--------------------------------------------------------------------------------
为什么不鼓励使用 Thread.suspend 和 Thread.resume?
Thread.suspend 从本质上就是易于死锁的。如果目标线程锁定在一个监视程序上,从而在关键系统资源挂起时保护资源,则在目标线程恢复前将没有线程能访问该资源。如果试图恢复目标线程的线程在调用 resume 之前试图锁定该监视程序,即出现死锁。这种死锁通常将自己显示为“冻结”进程。
--------------------------------------------------------------------------------
应该使用什么来代替 Thread.suspend 和 Thread.resume?
与 Thread.stop 一样,最谨慎的方法是让“目标”线程轮询一个指示所需线程状态(活动或挂起)的变量。当需要挂起状态时,线程将使用 Object.wait 进行等待。当线程恢复时,将使用 Object.notify 通知目标线程。
例如,假定 applet 包含下列 mousePressed 事件处理程序,它将触发名为 blinker 的线程的状态:
private boolean threadSuspended;
Public void mousePressed(MouseEvent e) {
e.consume();
if (threadSuspended)
blinker.resume();
else
blinker.suspend(); // 易于死锁!
threadSuspended = !threadSuspended;
}
用下列代码替代上述事件处理程序,即可避免使用 Thread.suspend 和 Thread.resume:
public synchronized void mousePressed(MouseEvent e) {
e.consume();
threadSuspended = !threadSuspended;
if (!threadSuspended)
notify();
}
然后将下列代码添加到“run loop”中:
synchronized(this) {
while (threadSuspended)
wait();
}
wait 方法将抛出 InterruptedException 异常,因此它必须位于 try ... catch 子句内。最好是将它插入到与 sleep 相同的子句中。sleep 后面(而不是前面)应该进行检查,以在线程“恢复”时立即重绘窗口。最终的 run 方法如下所示:
public void run() {
while (true) {
try {
Thread.currentThread().sleep(interval);
synchronized(this) {
while (threadSuspended)
wait();
}
} catch (InterruptedException e){
}
repaint();
}
}
注意:mousePressed 方法中的 notify 和 run 方法中的 wait 位于 synchronized 块内部。这是语言所要求的,可确保 wait 和 notify 的序列化。从实际应用来说,这消除了导致“挂起”线程丢失 notify 并无限期地保持挂起状态的竞争情况。
尽管 Java 中同步的费用随着平台的成熟不断下降,但它永远不会是免费的。用户可以使用一种简易技巧来删除添加在每一次“run loop”中的同步。前面添加的同步块被一段稍复杂的代码所替代(这段代码只有在实际挂起时才进入同步块):
if (threadSuspended) {
synchronized(this) {
while (threadSuspended)
wait();
}
}
最终的 run 方法为:
public void run() {
while (true) {
try {
Thread.currentThread().sleep(interval);
if (threadSuspended) {
synchronized(this) {
while (threadSuspended)
wait();
}
}
} catch (InterruptedException e){
}
repaint();
}
}
在没有提供显式同步前,threadSuspended 必须为 volatile,以确保挂起请求的快速通讯。
--------------------------------------------------------------------------------
是否可以利用这两种技术产生能安全“停止”或“挂起”的线程?
是,这一点显而易见。但要注意的一个细节是:目标线程可能在另一个线程试图停止它时就已经挂起。如果 stop 方法仅将状态变量 (blinker) 设置为 null,则目标线程将仍然挂起(在监视程序上等待),而不是象它所应该的那样悄悄退出。如果该 applet 被重新启动,则最终可能会出现多个线程在监视程序上等待,从而导致错误行为。
为了解决该问题,stop 方法必须确保目标线程能在挂起时立即恢复。一旦目标线程恢复后,它必须立即识别出自己已被停止并悄悄退出。下面是最终的 run 和 stop 方法:
public void run() {
Thread thisThread = Thread.currentThread();
while (blinker == thisThread) {
try {
thisThread.sleep(interval);
synchronized(this) {
while (threadSuspended && blinker==thisThread)
wait();
}
} catch (InterruptedException e){
}
repaint();
}
}
public synchronized void stop() {
blinker = null;
notify();
}
如果 stop 方法调用 Thread.interrupt(如前所述),则它不必调用 notify,但仍必须实现同步。这可以确保目标线程不会因为偶然情况错过中断。
--------------------------------------------------------------------------------
对于 Thread.destroy 又该怎么办?
Thread.destroy 从来就没有实现。如果它已经实现,则将易于出现 Thread.suspend 方式的死锁(实际上,它大致等价于 Thread.suspend 而没有后续的 Thread.resume)。我们现在还没有实现它,同时也不鼓励使用它(防止将来实现它)。尽管它易于死锁,但在有些情况下程序宁愿冒死锁危险也不愿立即退出。
还有很多waring,也没法一一说,你就去看相应的jdk1.2的文档吧