Chinaunix

标题: 不知道用什么方法能作到不让JAVA的程序多次执行。 [打印本页]

作者: cnndj    时间: 2006-08-04 17:53
标题: 不知道用什么方法能作到不让JAVA的程序多次执行。
是这样的,
现在已经开发好一个JAVA的应用程序test,但是在CMD窗口下执行java test可以正常执行,

但是当你再开一个CMD窗口,再执行java test还是可以正常执行,

主要是这个程序是处理数据库的一个应用程序,这样开两个窗口都执行这一个test程序的话,就会出现一条数据,处理了两次。我现在想找一个方法,让这个程序打开之后再想在其它窗口再执行这个程序就会告诉对方不能执行,而程序也不会再启动!!
作者: jhsea3do    时间: 2006-08-04 18:34
加锁
作者: sakulagi    时间: 2006-08-04 20:11
我理解,只能通过对本地资源加锁的方法。比如用JNI对信号量加锁。对本地磁盘文件加锁,或者占用某个特定端口。等等
作者: cnndj    时间: 2006-08-04 23:49
原帖由 sakulagi 于 2006-8-4 20:11 发表
我理解,只能通过对本地资源加锁的方法。比如用JNI对信号量加锁。对本地磁盘文件加锁,或者占用某个特定端口。等等


你说的占用某个特定的端口,这个方法我不知道怎么实现,但是我觉得很不错,希望能不能再指导一下小弟。
作者: perryhg    时间: 2006-08-05 02:05
public class MainStarter
{
    private static final int port = 2323;

    public static void main(String[] args)
    {
         try{
             ServerSocket ssk = new ServerSocket(port);
             //other code here
         }catch (Exception e)
         {
             //The program has already run
         }
    }
}

这样,当你的程序运行到 ServerSocket ssk = new ServerSocket(port);的时候,就会监听一个端口,而当你第二个相同的程序运行的时候,由于端口已经被占用,第二个程序就会发生SocketException从而导致后面的代码不会被执行。

[ 本帖最后由 perryhg 于 2006-8-5 02:07 编辑 ]
作者: moumoulrc    时间: 2006-08-05 11:49
原帖由 perryhg 于 2006-8-5 02:05 发表
public class MainStarter
{
    private static final int port = 2323;

    public static void main(String[] args)
    {
         try{
             ServerSocket ssk = new ServerSocket(port);
...

呵呵,可以接着来个System.exits(1);
作者: ruknow    时间: 2006-08-05 13:35
数据库表做个标记
作者: perryhg    时间: 2006-08-05 17:31
原帖由 ruknow 于 2006-8-5 13:35 发表
数据库表做个标记

用数据库可以做到多个客户端的情况下保证只有一个客户端运行,用Socket只能保证一台机器上防止重复运行。不过,socket有个好处,就是万一程序出错退出,Socket大多数情况都可以自动销毁,而文件锁定或者数据库标记就得手工清理了,否则这个程序就再也不能运行了。
作者: yeshenghai    时间: 2006-08-05 19:58
原帖由 perryhg 于 2006-8-5 17:31 发表

用数据库可以做到多个客户端的情况下保证只有一个客户端运行,用Socket只能保证一台机器上防止重复运行。不过,socket有个好处,就是万一程序出错退出,Socket大多数情况都可以自动销毁,而文件锁定或者数据库标 ...

数据库做标记,具体是怎么样的?能举一下例子吗?
作者: wobushiwo    时间: 2006-08-06 17:23
根据lz的情况,我推荐 socket 的方式
作者: ruknow    时间: 2006-08-07 00:44
原帖由 perryhg 于 2006-8-5 17:31 发表

用数据库可以做到多个客户端的情况下保证只有一个客户端运行,用Socket只能保证一台机器上防止重复运行。不过,socket有个好处,就是万一程序出错退出,Socket大多数情况都可以自动销毁,而文件锁定或者数据库标记就得手工清理了,否则这个程序就再也不能运行了。


放在事务中处理就不会出现问题了
作者: perryhg    时间: 2006-08-07 21:36
原帖由 ruknow 于 2006-8-7 00:44 发表


放在事务中处理就不会出现问题了

是啊,可是你得有个支持事务的容器,代码量也增加不少,如果是一个大型的系统应用,而且本来就有支持事务的应用服务器的话可以考虑这个方案,如果仅仅是一个单机的应用,就不用那么复杂了吧。
作者: ruknow    时间: 2006-08-08 00:21
原帖由 perryhg 于 2006-8-7 21:36 发表

是啊,可是你得有个支持事务的容器,代码量也增加不少,如果是一个大型的系统应用,而且本来就有支持事务的应用服务器的话可以考虑这个方案,如果仅仅是一个单机的应用,就不用那么复杂了吧。


利用数据库本身的事务管理

当然得看实际数据操作情况,不是所有情况都适用
作者: perryhg    时间: 2006-08-08 01:14
原帖由 ruknow 于 2006-8-8 00:21 发表


利用数据库本身的事务管理

当然得看实际数据操作情况,不是所有情况都适用

如果是用数据库本身的事务管理,那么当程序的一个Instance还没运行完毕的时候,这个事务还没有commit,就是说这个数据库标记对其他人是不可见的,所以程序的其他instance还是会运行,那么如何防止程序多个Instance同时运行呢?
作者: wobushiwo    时间: 2006-08-08 12:01
不用事务直接 lock table

怎么看都不是很好,本地的 socket 就行了吧
作者: ruknow    时间: 2006-08-09 01:12
原帖由 perryhg 于 2006-8-8 01:14 发表

如果是用数据库本身的事务管理,那么当程序的一个Instance还没运行完毕的时候,这个事务还没有commit,就是说这个数据库标记对其他人是不可见的,所以程序的其他instance还是会运行,那么如何防止程序多个Insta ...


他的问题是

是处理数据库的一个应用程序,这样开两个窗口都执行这一个test程序的话,就会出现一条数据,处理了两次


得看具体业务,如果这样的话,如果不是同时启动多个Instace,而是多次启动,总有个标记来说明数据已被处理过了。

数据库一张表做标记,启动程序时修改标记为已启动状态并commit,再处理业务,业务处理失败或完成后再恢复标记。
(不要告诉我在查表并修改提交的ms级时间启动两个Instance :)
作者: wobushiwo    时间: 2006-08-09 09:44
数据库一张表做标记,启动程序时修改标记为已启动状态并commit,再处理业务,业务处理失败或完成后再恢复标记。


其实也有不妥之处,跟文件还是一样

比如 “启动程序时修改标记为已启动状态并commit” 处理业务,假如失败或完成,那恢复标记什么的是没问题的

假如 “启动程序时修改标记为已启动状态并commit” 后就意外出问题呢?并没有执行意外的处理部分(程序中断)

那个标记还是依然存在

其实那就跟文件一样了,先建立锁文件,再处理,结束或有意外什么的再做处理

[ 本帖最后由 wobushiwo 于 2006-8-9 09:45 编辑 ]
作者: tinywind    时间: 2006-08-09 10:12
用数据库的好处是可以支持分布式应用的同步,用文件比较适合本机系统,用socket其实比较少见。
从扩展性来说的话数据库是个更好的解决方案。
作者: ruknow    时间: 2006-08-10 01:04
原帖由 wobushiwo 于 2006-8-9 09:44 发表


其实也有不妥之处,跟文件还是一样

比如 “启动程序时修改标记为已启动状态并commit” 处理业务,假如失败或完成,那恢复标记什么的是没问题的

假如 “启动程序时修改标记为已启动状态并commit” 后就意 ...


java里面有finally可以保证执行恢复,

如果是JVM崩溃就没说了,不过这种情况不是程序有问题一般不会出现吧
作者: perryhg    时间: 2006-08-10 01:15
原帖由 ruknow 于 2006-8-9 01:12 发表


他的问题是



得看具体业务,如果这样的话,如果不是同时启动多个Instace,而是多次启动,总有个标记来说明数据已被处理过了。

数据库一张表做标记,启动程序时修改标记为已启动状态并commit,再处理 ...

解决这样的问题只要在某个字段做个标记说明这条记录处理过了就可以了吧?用事务并不是为解决这个问题的吧。我们好像兜了一个大圈子,没准楼主就是要做这么简单的事情

作者: 我是好人    时间: 2006-08-10 11:24
锁表风险太高了。

建议使用临时文件做标识。
作者: wobushiwo    时间: 2006-08-10 12:26
原帖由 ruknow 于 2006-8-10 01:04 发表


java里面有finally可以保证执行恢复,

如果是JVM崩溃就没说了,不过这种情况不是程序有问题一般不会出现吧



我知道,请看清楚

其实也有不妥之处,跟文件还是一样


我是举例子说数据库标识跟文件标识的差别
作者: wobushiwo    时间: 2006-08-10 12:28
好像大家都没怎么看清楚讨论啊。。。。

我的意思是数据库标识,文件标识,锁表其实都差不多

根据LZ的情况,只本地判断,SOCKET是很好的,这种做法其实常用,TOMCAT等何尝不是
作者: james.liu    时间: 2006-08-10 19:26
通过写文件(ini操作快),检查文件信息也可以的。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2