·利用ssh2协议连接服务器,执行相关命令,监控redis运行情况
·利用http请求模拟登陆,监听tomcat
未解决
·资源释放问题,导致内存溢出
·断线重连问题
请求工具类 用作模拟登陆实现Runnable
package utils;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import org.apache.commons.lang.StringUtils;
public class HttpUtile {
/**
* 向指定URL发送GET方法的请求
*
* @param url
* 发送请求的URL
* @param param
* 请求参数,请求参数应该是name1=value1&name2=value2的形式。
* @return URL所代表远程资源的响应
*/
public static String sendGet(String url, String param) {
StringBuilder result = new StringBuilder();
BufferedReader in = null;
try {
String urlName = url + "?" + param;
URL realUrl = new URL(urlName);
// 打开和URL之间的连接
HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
conn.setRequestProperty("cache-control", "close");
conn.setRequestProperty("user-agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36");
conn.setRequestProperty("upgrade-insecure-requests","1");
conn.setRequestProperty("accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
conn.setRequestProperty("accept-encoding","gzip, deflate, br");
conn.setRequestProperty("accept-language:en-US,en","q=0.9,zh-CN;q=0.8,zh;q=0.7");
conn.setRequestMethod("GET");
// 建立实际的连接
conn.connect();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
if(StringUtils.isNotBlank(line))
result.append(line+"\n");
}
} catch (Exception e) {
System.out.println("发送GET请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输入流
finally {
try {
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return result.toString();
}
/**
* 向指定URL发送POST方法的请求
*
* @param url
* 发送请求的URL
* @param param
* 请求参数,请求参数应该是name1=value1&name2=value2的形式。
* @return URL所代表远程资源的响应
*/
public static String sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
StringBuilder result = new StringBuilder();
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
// 设置通用的请求属性
conn.setRequestProperty("cache-control", "close");
conn.setRequestProperty("user-agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36");
conn.setRequestProperty("upgrade-insecure-requests","1");
conn.setRequestProperty("accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
conn.setRequestProperty("accept-encoding","gzip, deflate, br");
conn.setRequestProperty("accept-language:en-US,en","q=0.9,zh-CN;q=0.8,zh;q=0.7");
conn.setRequestMethod("POST");
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
if(StringUtils.isNotBlank(line))
result.append(line+"\n");
}
} catch (Exception e) {
System.out.println("发送POST请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输出流、输入流
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return result.toString();
}
}
ssh2协议连接服务器,
package model;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import utils.DataFormUtil;
import view.ServersVIew;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
public class ServerModel implements Runnable{
//字符编码默认是utf-8
private static final String DEFAULTCHART="UTF-8";
public static final long SAFE_LV_MIN_VALUE = 3;
public static final long LV_1_MIN_VALUE = 5;
public static final long LV_2_MIN_VALUE = 7;
private final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
private Connection conn;
private int id;
private String ip;
private String userName;
private String userPwd;
private String name;
//http请求参数
private String loginProt;
private String loginUrl;
private Map<String,String> loginParam;
private boolean state;
private String msg;
private Map<String,Object> data;
public Map<String, Object> getData() {
return data;
}
public void setData(Map<String, Object> data) {
this.data = data;
}
public ServerModel() {
msg = "就绪";
}
@Override
public void run() {
ServersVIew view = ServersVIew.getInstance();
try {
view.getTxtLogs().append("正在连接:"+getTag()+"....");
if(open()){
view.getTxtLogs().append(getTag()+"\t连接成功");
}else{
view.getTxtLogs().append(getTag()+"\t连接失败,用户名或密码错误");
ServersVIew.getInstance().updateRow(this);
}
} catch (IOException e) {
msg = "\t访问主机受限,请重试";
view.getTxtLogs().append(getTag()+"\t访问主机受限,请重试");
ServersVIew.getInstance().updateRow(this);
}
while(view.isRun()){
if(!state){//更新信息
ServersVIew.getInstance().updateRow(this);
return;
}
try {
Thread.sleep(90);
update();
} catch (IOException e) {
ServersVIew.getInstance().getTxtLogs().append(getTag()+":"+e.getMessage());
msg = e.getMessage();
} catch (InterruptedException e) {
ServersVIew.getInstance().getTxtLogs().append(getTag()+":"+e.getMessage());
}
//更新信息
ServersVIew.getInstance().updateRow(this);
}
close();
Thread.currentThread();
}
@Override
public String toString() {
return "ServerModel [ip=" + ip + ", userName=" + userName + ", userPwd="
+ userPwd + ", name=" + name + "]";
}
public boolean open() throws IOException {
conn = new Connection(getIp());
conn.connect();//连接
if (conn.authenticateWithPassword(getUserName(), getUserPwd())){
data = new HashMap<String, Object>();
state = true;
return true;
}else{
msg = "用户名或密码错误";
}
state = false;
return false;
}
public void close(){
msg = "就绪";
data.clear();
data = null;
state = false;
conn.close();
ServersVIew.getInstance().getTxtLogs().append(getTag()+"\t已断开连接");
ServersVIew.getInstance().updateRow(this);
}
/**
* 解析脚本执行返回的结果集
* @author Ickes
* @param in 输入流对象
* @param charset 编码
* @since V0.1
* @return
* 以纯文本的格式返回
*/
private ArrayList<String> processStdout(InputStream in, String charset){
InputStream stdout = new StreamGobbler(in);
ArrayList<String> list = new ArrayList<String>();
try {
BufferedReader br = new BufferedReader(new InputStreamReader(stdout,charset));
String line=null;
while((line=br.readLine()) != null){
list.add(line);
}
} catch (UnsupportedEncodingException e) {
ServersVIew.getInstance().getTxtLogs().append(this.name+":"+e.getMessage());
} catch (IOException e) {
ServersVIew.getInstance().getTxtLogs().append(this.name+":"+e.getMessage());
}
return list;
}
public void update() throws IOException {
Session session = conn.openSession();
session.requestPTY("vt100", 80, 24, 640, 480, null);
session.execCommand("stat /data/dump.rdb | grep -i Modify | awk -F. '{print $1}' | awk '{print $2$3}'| awk -F- '{print $1$2$3}' | awk -F: '{print $1$2$3}';date;netstat -nat|grep -i \"843\"|wc -l");//执行命令
ArrayList<String> list = processStdout(session.getStdout(),DEFAULTCHART);
Date mod;
try {
//获取dump.rdb modify
data.put("modify", mod=sdf.parse(list.get(0)));
} catch (ParseException e) {
mod = null;
data.put("modify", "X");
}
Date sys = getDate(list.get(1));
//获取系统时间
data.put("date", sys);
//获取报警级别
data.put("lv", getLv(sys,mod));
//获取聊天连接数
data.put("session", list.get(2));
msg = DataFormUtil.getNormal(new Date());
session.close();
}
private int getLv(Date sys,Date mod){
if(sys == null || mod == null){
return -1;
}
long diff = sys.getTime() - mod.getTime();
diff /= 1000*60;
if(diff <= SAFE_LV_MIN_VALUE){
return 0;
}
if(diff <= LV_1_MIN_VALUE){
return 1;
}
if(diff <= LV_2_MIN_VALUE){
return 2;
}
return 3;
}
@SuppressWarnings("deprecation")
private Date getDate(String str){
Date date = new Date(str);
date.setHours(date.getHours()-14);
return date;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPwd() {
return userPwd;
}
public void setUserPwd(String userPwd) {
this.userPwd = userPwd;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean getState() {
return state;
}
public void setState(boolean state) {
this.state = state;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
private String getTag(){
return name+"|"+ip;
}
}
读取xml服务器配置信息
package utils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import model.ServerModel;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
import view.ServersVIew;
@SuppressWarnings("unused")
public class ServerLoader extends DefaultHandler implements Runnable{
private static final int RE_OR_LOAD_ALL = 0x23;
private static final int RELOAD_ONE = 0x24;
private static final int LOAD_NEW = 0x25;
private ServerModel server;
private List<ServerModel> list;
private int loadType;
private boolean name = false;
private boolean host = false;
private boolean username = false;
private boolean password = false;
/**
* Start processing of an element.
* @param namespaceURI Namespace URI
* @param localName The local name, without prefix
* @param qName The qualified name, with prefix
* @param atts The attributes of the element
*/
@Override
public void startElement(String uri, String localName, String qName,
Attributes atts) throws SAXException {
if (qName.equals("server")) {
server = new ServerModel();
}
if(qName.equals("name")){
name = true;
}
if(qName.equals("host")){
host = true;
}
if(qName.equals("username")){
username = true;
}
if(qName.equals("password")){
password = true;
}
}
@Override
public void endElement(String namespaceURI, String localName, String qName)
throws SAXException {
if(name){
name = false;
}
if(host){
host = false;
}
if(username){
username = false;
}
if(password){
password = false;
}
if (qName.equals("server")) {
server.setId(list.size());
list.add(server);
}
}
@Override
public void characters(char[] ch, int start, int length) {
String txt = new String(ch, start, length);
if(name){
server.setName(txt);
}
if(host){
server.setIp(txt);
}
if(username){
server.setUserName(txt);
}
if(password){
server.setUserPwd(txt);
}
}
private ServerLoader(int loadType){
this.loadType = loadType;
this.list = new ArrayList<ServerModel>();
ServersVIew.getInstance().submit(this);
}
private ServerLoader(int loadType,ServerModel serverModel){
this.server = serverModel;
this.loadType = loadType;
this.list = new ArrayList<ServerModel>();
ServersVIew.getInstance().submit(this);
}
@Override
public void run() {
try {
if(ServersVIew.getInstance().isRun()){
ServersVIew.getInstance().stop();
}
XMLReader parser = XMLReaderFactory.createXMLReader();
parser.setContentHandler(this);
parser.parse("resources/servers.xml");
ServersVIew.getInstance().setServers(list);
ServersVIew.getInstance().freshTable();
ServersVIew.getInstance().btn_reable();
ServersVIew.getInstance().getTxtLogs().append("一共导入"+list.size()+"台远程主机");
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void loadServers(){
new ServerLoader(RE_OR_LOAD_ALL);
}
public static void loadServer(ServerModel serverModel) {
new ServerLoader(RELOAD_ONE,serverModel);
}
public static void SaveServers(){
}
public static void SaveServer(){
}
public static void DeleteServer(){
}
public static void Clear(){
}
}
用作日志输出
package view;
import javax.swing.JTextArea;
import utils.DataFormUtil;
public class LogView extends JTextArea{
private static final long serialVersionUID = -6943271510465951839L;
@Override
public void append(String str) {
synchronized (this) {
super.append("【"+DataFormUtil.getNormal(System.currentTimeMillis())+"】"+str+"\n");
this.setCaretPosition(this.getText().length());
}
}
}
table 用作展示服务器信息
package view;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.concurrent.Executors;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import model.ServerModel;
import utils.DataFormUtil;
import utils.ServerLoader;
public class TableView extends JTable implements MouseListener{
private static final long serialVersionUID = 3939576385154700713L;
private final String[] colHader = {"主机","ip","主机时间","redis","聊天连接数","信息"};
private final String KEY_BTN_OPEN = "连接";
private final String KEY_BTN_CLOSE = "断开";
private List<ServerModel> servers;
private JPopupMenu selected,unSelected = null; // 弹出菜单
private JMenuItem serverBtn,reloadBtn;
public TableView(List<ServerModel> servers){
this.servers = servers;
this.setRowHeight(25);
this.setAutoCreateColumnsFromModel(true);//允许刷新
//创建表格模型.
DefaultTableModel model = getHeadModel();
this.setModel(model); //设置表格模型.
selected = new JPopupMenu();
serverBtn = new JMenuItem(KEY_BTN_OPEN);
serverBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
serverAction(e);
}
});
selected.add(serverBtn);
reloadBtn = new JMenuItem("重新刷新");
reloadBtn.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
serverAction(e);
}
});
this.add(selected);
unSelected = new JPopupMenu();
this.add(unSelected);
this.addMouseListener(this);
}
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
public void fresh(List<ServerModel> servers){
this.servers = servers;
//创建表格模型.
DefaultTableModel model = getHeadModel();
this.setModel(model); //设置表格模型.
for(ServerModel server : servers){
Vector<Object> vec = new Vector<Object>();
vec.add(server.getName());
vec.add(server.getIp());
vec.add("");
vec.add("");
vec.add("");
vec.add(server.getMsg());
model.addRow(vec);
}
}
private DefaultTableModel getHeadModel(){
return new DefaultTableModel(colHader,0);
}
@Override
public void mouseClicked(MouseEvent e) {
if(e.getButton()==MouseEvent.BUTTON3){
int rowId = this.getSelectedRow();
if(rowId >= 0){
ServerModel server = servers.get(rowId);
if(server.getState()){
serverBtn.setText(KEY_BTN_CLOSE);
reloadBtn.setEnabled(false);
}else{
serverBtn.setText(KEY_BTN_OPEN);
reloadBtn.setEnabled(true);
ServersVIew.getInstance().run();
}
selected.show(this, e.getX(), e.getY());
}else{
}
}
}
public void serverAction(ActionEvent e){
String key = e.getActionCommand();
ServerModel server = servers.get(this.getSelectedRow());
if(key.equals(KEY_BTN_OPEN)){
Executors.newSingleThreadExecutor().submit(server);
}else if(key.equals(KEY_BTN_CLOSE)){
server.close();
}
}
public void reloadAction(){
int rowId = this.getSelectedRow();
ServerLoader.loadServer(servers.get(rowId));
}
public void updateRow(ServerModel server) {
int rowId = server.getId();
if(server.getState()){
Map<String, Object> map = server.getData();
// 0,1 ,"主机时间","redis","聊天连接数","信息"
// data.put("lv", getLv(getDate(list.get(1)),getFormat(list.get(0))));
// data.put("modify", getFormat(list.get(0)));
// data.put("date", getDate(list.get(1)));
// data.put("session", list.get(2));
this.setValueAt(DataFormUtil.getNormal(map.get("date")), rowId, 2);
String color;
switch((Integer)map.get("lv")){
case 0:color = "#057748";break;
case 1:color = "#6B8E32";break;
case 2:color = "#FF1493";break;
case 3:color = "#FF0000";break;
default:color = "#e3e3e3";
}
String redis = "<html><font color='"+color+"'>"+((Integer)map.get("lv")>-1?DataFormUtil.getNormal(map.get("modify")):map.get("modify"))+"</font></html>";
this.setValueAt(redis, rowId, 3);
this.setValueAt(map.get("session"), rowId, 4);
this.setValueAt(server.getMsg(), rowId, 5);
}else{
this.setValueAt("", rowId, 2);
this.setValueAt("", rowId, 3);
this.setValueAt("", rowId, 4);
this.setValueAt(server.getMsg(), rowId, 5);
}
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
}
GUI主程序
package view;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import model.ServerModel;
import utils.ServerLoader;
public class ServersVIew extends JFrame{
private static class Single{
private final static ServersVIew dj = new ServersVIew();
}
private static final long serialVersionUID = -8160006559858640072L;
private final int CORE_POOL_SIZE = 100;
private final int MAXIMUM_POOL_SZIE = 300;
private final int KEEP_ALIVE_TIME = 30;
private final int WORK_QUEUE_SIZE = 5000;
private ThreadPoolExecutor executor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SZIE, KEEP_ALIVE_TIME, TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(WORK_QUEUE_SIZE), new ThreadPoolExecutor.AbortPolicy());
private boolean isRun = false;
private int width = 1600;
private int height = 900;
private ImageIcon[] link = new ImageIcon[2];
private List<ServerModel> servers = new ArrayList<ServerModel>();
public static ServersVIew getInstance(){
return Single.dj;
}
private JTextArea txtLogs = new LogView();
private TableView table;
private JButton btn;
private ServersVIew(){
try {
Image img = ImageIO.read(new File("resources/imgs/close.png")).getScaledInstance(50, 50, BufferedImage.SCALE_DEFAULT);
link[0] = new ImageIcon(img);
img = ImageIO.read(new File("resources/imgs/open.png")).getScaledInstance(50, 50, BufferedImage.SCALE_DEFAULT);
link[1] = new ImageIcon(img);
img = ImageIO.read(new File("resources/imgs/ico.png"));
this.setIconImage(img);
} catch (IOException e) {
e.printStackTrace();
}
this.setTitle("Linux服务器监控器");
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(width, height);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.setLayout(new BorderLayout());
//左边
JPanel west = new JPanel();
west.setLayout(new GridLayout(1, 1));
JScrollPane scrollPane = new JScrollPane();
scrollPane.setViewportView(getTable());
west.add(scrollPane);
west.setBackground(Color.black);
west.setPreferredSize(new Dimension(width*2/3-5,height));
this.add(west,BorderLayout.WEST);
//右边
JPanel east = new JPanel();
east.setLayout(new BorderLayout());
east.setPreferredSize(new Dimension(width/3-5,height));
//右上
JPanel north = new JPanel();
north.setPreferredSize(new Dimension(width/3,height*7/8-20));
JScrollPane scrollPane2 = new JScrollPane();
north.setLayout(new GridLayout(1, 1));
north.add(scrollPane2);
txtLogs.setEditable(false);
txtLogs.setLineWrap(true);
scrollPane2.setViewportView(txtLogs);
east.add(north, BorderLayout.NORTH);
//右下
JPanel south = new JPanel();
south.setPreferredSize(new Dimension(width/3,height/8-10));
btn = new JButton("连接所有主机");//
btn.setIcon(link[1]);
btn.addMouseListener(new MouseAdapter(){
@Override
public void mouseClicked(MouseEvent e) {
if(!isRun){
btn.setText("断开所有主机");
btn.setIcon(link[0]);
start();
}else{
btn.setText("连接所有主机");
btn.setIcon(link[1]);
stop();
}
}
});
south.add(btn);
JButton btnload = new JButton("载入主机");
btnload.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
btn.setEnabled(false);
txtLogs.append("正在载入配置文件...");
ServerLoader.loadServers();
}
});
south.setLayout(new GridLayout(1, 2));
south.add(btnload);
east.add(south, BorderLayout.SOUTH);
this.add(east,BorderLayout.EAST);
this.setVisible(true); // 设置窗口为可见的,默认为不可见
}
public void btn_reable(){
btn.setEnabled(true);
btn.setText("连接所有主机");
btn.setIcon(link[1]);
}
public void freshTable() {
table.fresh(servers);
}
//getTable()方法代码.
private JTable getTable(){
if(table==null){ //检查表格是否为空.
table=new TableView(servers);//创建表格控件.
}
return table;
}
public void updateRow(ServerModel server) {
table.updateRow(server);
}
@Override
public void dispose() {
isRun = false;
super.dispose();
}
public void stop(){
txtLogs.append("正在断开所有主机...");
isRun = false;
}
public void start(){
if(servers.size()==0){
txtLogs.append("主机列表为空,先导入主机");
btn_reable();
}else{
txtLogs.append("正在连接所有主机...");
isRun = true;
for(ServerModel server : servers){
if(!server.getState()){
executor.submit(server);
}
}
}
}
public boolean isRun() {
return isRun;
}
public List<ServerModel> getServers() {
return servers;
}
public void setServers(List<ServerModel> servers) {
this.servers = servers;
}
public JTextArea getTxtLogs() {
return txtLogs;
}
public void setTxtLogs(LogView txtLogs) {
this.txtLogs = txtLogs;
}
public void run(){
isRun = true;
}
public void submit(Runnable runn){
executor.submit(runn);
}
}
启动入口
import view.ServersVIew;
public class Main {
public static void main(String[] args) {
ServersVIew.getInstance();
}
}
参考:
java发送http的get、post请求
java 连接Linux服务器并执行指令
java swing 创建 table 表格
ThreadPoolExecutor + Runnable