4.A启动的时候,获取A.lock文件的锁,如果拿到了证明没有A启动,则A运行;如果没有拿到锁,证明A已经启动了,或者是B判断的时候拿到了锁,如果是A已经启动了,不需要再次启动A,如果是B判断的时候拿到了锁,没关紧 要,反正B会再次启动A。
Step 2:加入Server
1.A用于守护B和Server,B用于守护A。
2.原理与Step 1 一致,只是A多个一个守护Serer的任务。
3.当A运行的时候,使用进程pid检测到Server已经挂了,就启动Server
4.如果Server与A都挂了,B会启动A,然后A启动Server
5.如果Server与B挂了,A启动Server与B
6.如果A与B都挂了,守护结束
Step 3:使用Shutdown结束守护,不然结束Server后会自动启动
四、实现
1、GuardA的实现
1 public class GuardA {
2 // GuardA用于维持自己的锁
3 private File fileGuardA;
4 private FileOutputStream fileOutputStreamGuardA;
5 private FileChannel fileChannelGuardA;
6 private FileLock fileLockGuardA;
7 // GuardB用于检测B的锁
8 private File fileGuardB;
9 private FileOutputStream fileOutputStreamGuardB;
10 private FileChannel fileChannelGuardB;
11 private FileLock fileLockGuardB;
13 public GuardA() throws Exception {
14 fileGuardA = new File(Configure.GUARD_A_LOCK);
15 if (!fileGuardA.exists()) {
16 fileGuardA.createNewFile();
17 }
18 //获取文件锁,拿不到证明GuardA已启动则退出
19 fileOutputStreamGuardA = new FileOutputStream(fileGuardA);
20 fileChannelGuardA = fileOutputStreamGuardA.getChannel();
21 fileLockGuardA = fileChannelGuardA.tryLock();
22 if (fileLockGuardA == null) {
23 System.exit(0);
24 }
26 fileGuardB = new File(Configure.GUARD_B_LOCK);
27 if (!fileGuardB.exists()) {
28 fileGuardB.createNewFile();
29 }
30 fileOutputStreamGuardB = new FileOutputStream(fileGuardB);
31 fileChannelGuardB = fileOutputStreamGuardB.getChannel();
32 }
34 /**
35 * 检测B是否存在
36 *
37 * @return true B已经存在
38 */
39 public boolean checkGuardB() {
40 try {
41 fileLockGuardB = fileChannelGuardB.tryLock();
42 if (fileLockGuardB == null) {
43 return true;
44 } else {
45 fileLockGuardB.release();
46 return false;
47 }
48 } catch (IOException e) {
49 System.exit(0);
50 // never touch
51 return true;
52 }
53 }
2、GuardServer的实现
1 public class GuardServer {
2 private String servername;
4 public GuardServer(String servername) {
5 this.servername = servername;
6 }
8 public void startServer(String cmd) throws Exception {
9 System.out.println("Start Server : " + cmd);
10 //将命令分开
11 // String[] cmds = cmd.split(" ");
12 // ProcessBuilder builder = new ProcessBuilder(cmds);
14 //
15 ProcessBuilder builder=new ProcessBuilder(new String[]{"/bin/sh","-c",cmd});
16 //将服务器程序的输出定位到/dev/tty
17 builder.redirectOutput(new File("/dev/tty"));
18 builder.redirectError(new File("/dev/tty"));
19 builder.start(); // throws IOException
20 Thread.sleep(10000);
21 }
23 /**
24 * 检测服务是否存在
25 *
26 * @return 返回配置的java程序的pid
27 * @return pid >0 返回的是 pid <=0 代表指定java程序未运行
28 * **/
29 public int checkServer() throws Exception {
30 int pid = -1;
31 Process process = null;
32 BufferedReader reader = null;
33 process = Runtime.getRuntime().exec("jps -l");
34 reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
35 String line;
36 while ((line = reader.readLine()) != null) {
37 String[] strings = line.split("\\s{1,}");
38 if (strings.length < 2)
39 continue;
40 if (strings[1].contains(servername)) {
41 pid = Integer.parseInt(strings[0]);
42 break;
43 }
44 }
45 reader.close();
46 process.destroy();
47 return pid;
48 }
3、GuardAMain实现
1 public class GuardAMain {
2 public static void main(String[] args) throws Exception {
3 GuardA guardA = new GuardA();
4 Configure configure = new Configure();
5 GuardServer server = new GuardServer(configure.getServername());
6 while (true) {
7 // 如果GuardB未运行 运行GuardB
8 if (!guardA.checkGuardB()) {
9 System.out.println("Start GuardB.....");
10 Runtime.getRuntime().exec(configure.getStartguardb());
11 }
12 // 检测服务器存活
13 if (server.checkServer() <= 0) {
14 boolean isServerDown = true;
15 // trip check
16 for (int i = 0; i < 3; i++) {
17 // 如果服务是存活着
18 if (server.checkServer() > 0) {
19 isServerDown = false;
20 break;
21 }
22 }
23 if (isServerDown)
24 server.startServer(configure.getStartserver());
25 }
26 Thread.sleep(configure.getInterval());
27 }
28 }
4、Shutdown实现
1 public class ShutDown {
2 public static void main(String[] args) throws Exception {
3 Configure configure = new Configure();
4 System.out.println("Shutdown Guards..");
5 for (int i = 0; i < 3; i++) {
6 Process p = Runtime.getRuntime().exec("jps -l");
7 BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
8 String line;
9 while ((line = reader.readLine()) != null) {
10 if (line.toLowerCase().contains("Guard".toLowerCase())) {
11 String[] strings = line.split("\\s{1,}");
12 int pid = Integer.parseInt(strings[0]);
13 Runtime.getRuntime().exec(configure.getKillcmd() + " " + pid);
14 }
15 }
16 p.waitFor();
17 reader.close();
18 p.destroy();
19 Thread.sleep(2000);
20 }
21 System.out.println("Guards is shutdown");
22 }
5、GuardB与GuardA类似
五、下载与使用
项目文件夹:guard_demo
下载地址:http://pan.baidu.com/s/1bn1Y6BX
最新内容请见作者的GitHub页:http://qaseven.github.io/
Java实现图书管理系统
本篇文章是对目前Java专栏已有内容的一个总结练习,希望各位小主们在学习完面向对象的知识后,可以阅览本篇文章后,自己也动手实现一个这样的demo来加深总结应用已经学到知识并进行巩固。
Java实现拼图小游戏(1)—— JFrame的认识及界面搭建
如果要在某一个界面里面添加功能的话,都在一个类中,会显得代码难以阅读,而且修改起来也会很困难,所以我们将游戏主界面、登录界面、以及注册界面都单独编成一个类,每一个类都继承JFrame父类,并且在类中创建方法来来实现页面
Java实现拼图小游戏(7)—— 计步功能及菜单业务的实现
注意由于我们计步功能的步数要在重写方法中用到,所以不能将初始化语句写在方法体内,而是要写在成员位置。在其名字的时候也要做到“见名知意”,所以我们给它起名字为step
Java实现拼图小游戏(7)—— 作弊码和判断胜利
当我们好不容易把拼图复原了,但是一点提示也没有,完全看不出来是成功了,那么我们就需要有判断胜利的功能去弹出“成功”类的图片,以便于玩家选择是重新开始还是退出小游戏
Java实现拼图小游戏(6)—— 移动图片(键盘监听实操练习)
当我们实现向上移动图片的时候,其实就是把空图片的下面一张图片往上移动,然后将空图片的下面那张图片设置为空图片,最后再调整初始位置为现在空图片所在位置即可,注意做完这些以后还要再加载图片,否则显示不出来
Java实现拼图小游戏(5)—— 美化界面(含源码阅读)
先加载的图片在上方,后加载的图片在下方,所以我们要把创建背景图的代码放在我们之前创建十五个小图片的代码后面,否则会出现背景图片将我们要拼的图片覆盖的情况