当前位置:编程学习 > JAVA >>

多线程并发请求数据,并记录线程的运行状态,在JTextArea中实时显示

实现这样一个小功能:
1、多条线程并发请求数据,当随机数为15时,弹出验证码对话框供用户输入,输入验证码长度为4时,对话框关闭,线程继续运行;当随机数为11时,请求获得数据,所有线程停止运行。
2、一条线程负责记录(1)中所有线程的运行状态,并在JTextArea中实时显示
现在的问题是:
1、当启动多条线程并发请求数据时,程序阻塞不运行了(图1)
2、日志信息不实时显示在JTextArea中,存在日志丢失的问题(图2)
图(1):程序阻塞了

图(2):日志丢失(程序中有记录日志,但显示日志的JTextArea中未显示)

1、Login.java文件(程序入口):
package UI;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

import biz.Robticket;
import biz.WriteLog;

public class Login implements ActionListener{
JFrame f = new JFrame("测试窗口");
JButton startBtn = new JButton("开  始");
//用来显示日志记录的文本域
public static JTextArea area = new JTextArea(10, 50);

public static void main(String[] args){
new Login().init();
}

public void init(){
Box verticalBox = Box.createVerticalBox();
JPanel p3 = new JPanel();
p3.add(startBtn);
//按钮添加事件
startBtn.addActionListener(this);
verticalBox.add(p3);

JPanel p4 = new JPanel();
JScrollPane scrollPane = new JScrollPane(area);
p4.add(scrollPane);
verticalBox.add(p4);

f.add(verticalBox);
f.setLocation(500, 300);
f.setResizable(false);
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}

@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == startBtn){
startBtn.setEnabled(false);

Robticket robticket = new Robticket();
new Thread(robticket,"线程1").start();
new Thread(robticket,"线程2").start();
/*new Thread(robticket,"线程3").start();
new Thread(robticket,"线程4").start();
new Thread(robticket,"线程5").start();
new Thread(robticket,"线程6").start();*/

WriteLog log =WriteLog.getInstance();
Thread t = new Thread(log,"日志线程");
t.start();
}
}
}


2、Robticket.java文件(多线程请求数据):
package biz;

import java.awt.Dimension;
import java.awt.TextField;
import java.awt.event.TextEvent;
import java.awt.event.TextListener;
import java.awt.event.WindowEvent;
import java.util.Random;

import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;

import listener.WdListener;

public class Robticket implements Runnable{
//线程停止标记
private  boolean stoped = false;
//验证码
private String code = null;
//随机数
Random random = new Random();
//记录日志对象
private WriteLog log;

public Robticket(){
log = WriteLog.getInstance();
}

public synchronized  void setCode(String code){
this.code = code;
notify();
}
public synchronized String getCode(){
try {
if(code == null){
wait();
}
} catch (Exception e) {
e.printStackTrace();
}
return code;
}

@Override
public void run() {
while(!stoped){
String threadName = Thread.currentThread().getName();
//产生一个随机数
int x = random.nextInt(20);

log.setNewRecord(threadName+" 正在运行..."+ x);

//当随机数为15时,打开验证码窗口等待输入4位验证码
if(x == 15){
log.setNewRecord("-----"+threadName+" 需要验证码-----");

new VerifyCodeDialog(threadName);
String code = getCode();

log.setNewRecord(threadName+" 验证码为:"+code);
}
//当随机数为11时,请求获得数据,线程终止运行
if(x == 11){
stoped = true;
log.setNewRecord("-----"+threadName+" 已获得数据,程序结束-----"+x);
break;
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

//验证码窗口
class VerifyCodeDialog extends WdListener implements TextListener{
JDialog dialog = new JDialog();
TextField codeTxt = new TextField(10);

public VerifyCodeDialog(String theadName){

codeTxt.addTextListener(this);

JPanel p = new JPanel();
p.add(new JLabel("验证码:"));
p.add(codeTxt);

dialog.setTitle(theadName);
dialog.addWindowListener(this);
dialog.add(p);
dialog.setLocation(400, 300);
dialog.setSize(new Dimension(200, 100));
dialog.setModal(true);//设置父窗口不可编辑
dialog.setVisible(true);
}

@Override
public void windowClosing(WindowEvent e) {
log.setNewRecord("验证码窗口关闭,运行停止...");
stoped = true;
code = null;
}

@Override
public void textValueChanged(TextEvent e) {
if(e.getSource() == codeTxt){
String code = codeTxt.getText();
//当输入验证码长度为4时,调用setCode设置验证码,关门对话框
if(code.length()==4){
setCode(code);
dialog.dispose();
}
}
}
}
}


3、WriteLog.java文件(写日志)
package biz;

import javax.swing.JTextArea;

import UI.Login;

public class WriteLog implements Runnable{

//记录日志的文本域
JTextArea area;

//一条记录
String newRecord = "";

private static WriteLog log;

//单例模式返回日志对象
public static WriteLog getInstance(){
if(log == null){
log = new WriteLog();
}
return log;
}

//获得新记录 无值则等待
public synchronized String getNewRecord(){
try {
if(newRecord == ""){
wait();
}
} catch (Exception e) {
e.printStackTrace();
}
String result = newRecord;
newRecord = "";

notify();

return result;
}
//设置新记录 有值则等待
public synchronized void setNewRecord(String record){
try {
if(newRecord != ""){
wait();
}else{
this.newRecord = record;
notify();
}
} catch (Exception e) {
e.printStackTrace();
}
}

@Override
public void run() {
while(true){
String newRecord = getNewRecord();
//日志框中打印日志
area = Login.area;
area.append(" "+newRecord+"\r\n");
area.setCaretPosition(area.getText().length());
}
}

}
多线程 并发 String 验证码 行业数据 --------------------编程问答-------------------- 少了一个WdListener.java文件,只实现WindowListener接口,啥也没做
package listener;

import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

public class WdListener implements WindowListener{

@Override
public void windowActivated(WindowEvent e) {
// TODO Auto-generated method stub

}

@Override
public void windowClosed(WindowEvent e) {
// TODO Auto-generated method stub

}

@Override
public void windowClosing(WindowEvent e) {
// TODO Auto-generated method stub

}

@Override
public void windowDeactivated(WindowEvent e) {
// TODO Auto-generated method stub

}

@Override
public void windowDeiconified(WindowEvent e) {
// TODO Auto-generated method stub

}

@Override
public void windowIconified(WindowEvent e) {
// TODO Auto-generated method stub

}

@Override
public void windowOpened(WindowEvent e) {
// TODO Auto-generated method stub

}


}
补充:Java ,  Java相关
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,