我的服务端对应很多用户,与每一个用户交互都是用的一个线程。用户的功能可以告诉服务端 “是”或者“否”我想在特定场景触发时,服务端让其他用户的功能都disable掉,然后只是enable一个用户的功能,并且只给这个用户30秒时间回答“是/否”,客户回答后,disable这个客户。如果用户超时,没有回答,视为回答否,仍然disable这个客户。我比较迷茫的是,30秒这个怎么做,多线程下有什么好的时钟之类的东西,可以不影响别的线程么,因为有时候是同时enable多个用户,让他们都作答“是否”,什么时钟是只影响当前这一个线程,而且在被通知用户的答案后会自动结束计时的呢。谢谢了!
import java.awt.event.*;
import java.text.SimpleDateFormat;
import java.util.*;import javax.swing.*;
import javax.swing.border.*;public class TestTimePieceJFrame extends JFrame {
ControlPanel controlPane = null; //-----------------控制面板
JTextField jTextField; public TestTimePieceJFrame() {
super();
init();
} private void init() {
controlPane = new ControlPanel(this);
add(controlPane);
setPreferredSize(new Dimension(300, 170));
pack();
setVisible(true);
setResizable(false);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
addKeyListener(new TimePieceKeyListener());
} public static void main(String[] args) {
new TestTimePieceJFrame();
;
} class TimePieceKeyListener extends KeyAdapter {
public void keyReleased(KeyEvent e) {
controlPane.keyReleased(e);
}
}
}
class ControlPanel extends JPanel {
private JFrame snakeFrame = null;
JLabel jLabel,jLabel1, jLabel2, jLabel3, jLabel4;
Date dateWhenStartJpanel;//保存程序启动时的时间
Date dateWhenClickF5;
Thread thread ;
public ControlPanel(JFrame snakeFrame) {
super();
this.snakeFrame = snakeFrame;
init();
} private void init() {
dateWhenStartJpanel = new Date();
setSize(608, 31);
setBackground(Color.WHITE);
setLayout(new FlowLayout());
setBorder(new LineBorder(Color.white, 5));
setLayout(new FlowLayout());
jLabel = new JLabel();
jLabel1 = new JLabel();
jLabel2 = new JLabel();
jLabel3 = new JLabel();
jLabel4 = new JLabel();
add(jLabel);
add(jLabel1);
add(jLabel2);
add(jLabel3);
add(jLabel4);
jLabel.setText("F5:开始计时 F6:停止计时");
} public void keyReleased(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_F5) {
dateWhenClickF5 = new Date();//sava time when click F5
thread = new Thread(new TimePieceRunnable())
;thread.start();
} else if (keyCode == KeyEvent.VK_F6) {
if(thread != null)thread.stop();
else prompt("请先按F5");
}
} class TimePieceRunnable implements Runnable {
public void run() {
while (true) {
Date tempDate = new Date();
String tempString = formateToTime(tempDate, "现在时间是 E kk:mm:ss:");
jLabel1.setText(tempString);
tempString = formateToTime(dateWhenStartJpanel,
"启动程序时间是 E kk:mm:ss:");
jLabel2.setText(tempString);
tempString = formateToTime(dateWhenClickF5,
"最近一次按动F5时间是 E kk:mm:ss:");
jLabel3.setText(tempString);
tempDate = getMillisOfTimeDifference(dateWhenClickF5, tempDate);
tempString = formateToTime(tempDate,
"最近一次按动F5到现在的时间差是 kk:mm:ss:");
jLabel4.setText(tempString);
try {
repaint();
Thread.sleep(100);////每隔0.1秒刷新一次
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} public String formateToTime(Date date, String timeRegex) {
//Date date = new Date();
//SimpleDateFormat f = new SimpleDateFormat("'BeiJing Time':yyyy年MM月dd日 E kk时mm分ss秒");
SimpleDateFormat f = new SimpleDateFormat(timeRegex);
String newTypeDate = f.format(date);
return newTypeDate; } public Date getMillisOfTimeDifference(Date date1, Date date2) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date1);
long timelnMillis1 = calendar.getTimeInMillis();
calendar.setTime(date2);
long timelnMillis2 = calendar.getTimeInMillis();
calendar.setTimeInMillis(timelnMillis2 - timelnMillis1);
return calendar.getTime();
}
private static int prompt(String promptMessage) {
return JOptionPane.showConfirmDialog(null, promptMessage, "友情提示",
JOptionPane.WARNING_MESSAGE);
}
}
我感觉wait可以, 用户做答后用notify, 行么?
建议看看API,用法很简单的,和普通线程操作都差不多
有道理,如果我准备好一个boolean answered,在向用户提出问题,等待“是否”答案之前就创建一个Timer,timer的任务定为30秒后把answered设置为yes, 如果用户在这期间回答“是否”,answered也会设置为yes。然后在这个之后用一个while(!answered){},这样只要不作答或者没超时就一直等待。这样子行么?因为这是个多玩家联机的游戏,用while()来检测的话会很慢或者影响游戏么?谢谢了
import java.io.*;
import java.net.*;public class Server
{
private ServerSocket server;
public Server() throws Exception
{
server = new ServerSocket(9999);
while (true)
{
Socket socket = server.accept();
new ListenThread(socket).start();
}
}
public static void main(String[] args) throws Exception
{
new Server();
}
private class ListenThread extends Thread
{
private Socket socket;
public ListenThread(Socket socket)
{
this.socket = socket;
}
public void run()
{
try
{
try
{
socket.setSoTimeout(30000); //设置socket超时时间为30秒
System.out.println("accept " + socket.getInetAddress().getHostAddress() + ":" + socket.getPort());
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream());
out.println("请选择(y/n)");
out.flush();
String str = in.readLine();
if (str.equalsIgnoreCase("y")) //用户选是,启动回显功能
{
socket.setSoTimeout(0); //不限制超时时间
System.out.println(socket.getInetAddress().getHostAddress() + ":" + socket.getPort() + "选择y");
while ((str = in.readLine()) != null)
{
out.println(str);
out.flush();
}
}
else
{
System.out.println(socket.getInetAddress().getHostAddress() + ":" + socket.getPort() + "选择n");
}
}
finally
{
System.out.println(socket.getInetAddress().getHostAddress() + ":" + socket.getPort() + "关闭");
socket.close();
}
}
catch (SocketTimeoutException e) //捕获到超时异常
{
System.out.println(socket.getInetAddress().getHostAddress() + ":" + socket.getPort() + "超时");
try
{
socket.close();
}
catch (IOException e1)
{}
}
catch (Exception e)
{}
}
}
}
有道理啊,不过我发现lock已经解决问题了哈,谢谢了。 我给分了