欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java程序單實(shí)例運(yùn)行的簡單實(shí)現(xiàn)

 更新時間:2021年08月25日 09:31:05   作者:FXBStudy  
這篇文章主要介紹了Java程序單實(shí)例運(yùn)行的簡單實(shí)現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

需求

最近做了個java項(xiàng)目,功能完成后打包安裝了,發(fā)現(xiàn)可以點(diǎn)開多個實(shí)例,因?yàn)樽烂骘@示托盤,所以點(diǎn)一次就會出現(xiàn)一個托盤,并且系統(tǒng)也多了好幾個javaw進(jìn)程,這樣的話就不能保證程序的健壯性了,所以需要做一個判斷讓程序只運(yùn)行一個實(shí)例。

實(shí)現(xiàn)方式

Java沒有提供這樣的機(jī)制。從操作系統(tǒng)的觀點(diǎn)來看,一個啟動的Java Application僅僅是一個JVM的運(yùn)行實(shí)例。運(yùn)行相同Application的兩個實(shí)例,僅僅是運(yùn)行兩個無關(guān)的JVM。

只有讓多個運(yùn)行實(shí)例之間有一個既定的通訊機(jī)制就可以保證只有一個實(shí)例運(yùn)行。

因?yàn)橐紤]平臺無關(guān),java程序的實(shí)例控制不應(yīng)該使用系統(tǒng)的內(nèi)核對象來完成,那么我們就必須找到其它的、可以獨(dú)享的資源。實(shí)際上,一臺機(jī)器無論是在什么操作系統(tǒng)上,網(wǎng)絡(luò)端口都是獨(dú)享的,也就是說基于網(wǎng)絡(luò)端口這個獨(dú)享的原理,我們可以很方便地讓我們的Java程序?qū)崿F(xiàn)在內(nèi)存里面只有一個運(yùn)行實(shí)例這個功能,而且這個功能的實(shí)現(xiàn)是與平臺無關(guān)的。

使用端口號控制的方式,先創(chuàng)建端口,運(yùn)行的時候再判斷端口是否被占用來判斷是否啟動新實(shí)例。

文件鎖的方式,這種方式的用法在于運(yùn)行程序的時候?qū)⑽募湘i,然后判斷這個文件是否被鎖進(jìn)而來判斷是否要運(yùn)行一個新實(shí)例。

使用端口號+文件的方式,這種方式的用法在于啟動的時候創(chuàng)建一個文件,關(guān)閉的時候刪掉這個文件,當(dāng)然僅僅這么一個操作不能起到上述要求的,如果非法關(guān)閉的話,文件還存在就不能滿足要求,只能是再加上一個端口的控制,即當(dāng)端口被占用并且文件存在的情況下就停止運(yùn)行新實(shí)例,否則啟動一個實(shí)例,經(jīng)試驗(yàn)這種方式可以得到滿足。

代碼實(shí)現(xiàn)

第一種實(shí)現(xiàn)(端口控制)

//方案:使用java.net.ServerSocket
//問題:打開服務(wù)端口可能會受到防火墻的影響;可能和別的端口沖突。
import java.io.*;
import java.net.*;
public class OneInstance_2
{
    private static ServerSocket listenerSocket;
    public static void main(String[] args)
    {
        try
        {
            listenerSocket = new ServerSocket(2004);
            //At this point, no other socket may listen on port 2004.
        }
        catch(java.net.BindException e)
        {
            System.err.println("A previous instance is already running....");
            System.exit(1);
        }
        catch(final IOException e)     // an unexpected exception occurred
        {
            System.exit(1);
        }
        // Do some work here.....
    }
}

第二種實(shí)現(xiàn)(文件鎖)

/*方案:使用Java的加鎖文件機(jī)制,idea相當(dāng)簡單,讓運(yùn)行實(shí)例通過java.nio.channels.FileLock獲得一個"well-known"文件的互斥鎖。*/
//存在的問題:平臺相關(guān)
import java.io.*;
import java.nio.channels.*;
public class OneInstance_1 {
  public static void main(String[] args) throws Exception {
    FileLock lck = new FileOutputStream("C:\\flagFile").getChannel().tryLock();         
    if(lck == null) {
      System.out.println("A previous instance is already running....");
      System.exit(1);
    }
    System.out.println("This is the first instance of this program...");
    // Do some work here.....
  }
}
//方案3:使用File.createNewFile() and File.deleteOnExit()
//問題:文件可能因?yàn)槟承┰虿荒鼙粍h除,即使利用Runtime.addShutdownHook()也有可能產(chǎn)生這種情況。
import java.io.*;
public class OneInstance_3
{
    public static void main(String[] args) throws Exception
    {
        File flagFile = new File("C:\\flagFile");
        if(false == flagFile.createNewFile())
        {
            System.out.println("A previous instance is already running....");
            System.exit(1);
        }
        flagFile.deleteOnExit();
        System.out.println("This is the first instance of this program...");    // Do some work here.....
    }
}

第三種方式(端口+文件鎖)

public static void main(String[] args) throws IOException
{ 
    //創(chuàng)建lock.java文件 
    String filePath = new File("IDRCallDll").getAbsolutePath().substring(0, 
            new File("IDRCallDll").getAbsolutePath().lastIndexOf("\\")); 
    File getFile = new File(filePath + "\\" + "lock.java"); 
    System.out.println(getFile.getPath());
 
    //判斷端口是否被占用 
    boolean flag = isLoclePortUsing(20520); 
    System.out.println(flag);
 
    //如果文件存在并且端口被占用則退出 
    if (getFile.exists() && flag)
    {
 
        new MyTray().showDialog(); 
        System.exit(0); 
    }
 
    try
    { 
        Socket sock = new Socket("127.0.0.1", 20520);// 創(chuàng)建socket,連接20520端口 
    }
    catch (Exception e)
    { 
        System.out.println("端口被占用!"); 
    }
 
    final Class<?> clazz = (Class<?>) JavaCall.class; 
    final boolean isWindows = System.getProperty("os.name").contains( 
                                  "Windows"); 
    final List<String> args1 = new ArrayList<String>(); 
    args1.add(isWindows ? "javaw" : "java"); 
    args1.add("-Xmx" + 128 + "M"); 
    args1.add("-cp");
     args1.add(System.getProperty("java.class.path")); 
    args1.add("-Djava.library.path=" 
              + System.getProperty("java.library.path")); 
    args1.add(clazz.getCanonicalName()); 
    // logger.info("start " + args1.toString()); 
    final ProcessBuilder pb = new ProcessBuilder(args1); 
    pb.redirectErrorStream(true);  
    try
    { 
        /**
        * 讀身份證信息程序
        */
 
        pb.start(); 
    }
    catch (Exception e)
    { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
    }  
 
    RandomAccessFile r = new RandomAccessFile( 
        filePath + "\\" + "lock.java", "rws"); 
    FileChannel temp = r.getChannel(); 
    FileLock fl = temp.lock(); 
}
 
/**
* 判斷端口是否被占用
* @param port
* @return
*/
 
public static boolean isLoclePortUsing(int port)
{ 
    boolean flag = true; 
    try
    { 
        flag = isPortUsing("127.0.0.1", port); 
    }
    catch (Exception e)
    { 
    } 
    return flag; 
}
 
public static boolean isPortUsing(String host, int port) throws UnknownHostException
{ 
    boolean flag = false; 
    InetAddress theAddress = InetAddress.getByName(host); 
    System.out.println(theAddress);
 
    try
    { 
        ServerSocket socket = new ServerSocket(port); 
        flag = true; 
    }
    catch (IOException e)
    { 
        System.out.println("beizhanyong"); 
    } 
    return flag; 
}

以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • mybatis TypeHandler注入spring的依賴方式

    mybatis TypeHandler注入spring的依賴方式

    這篇文章主要介紹了mybatis TypeHandler注入spring的依賴方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Java遞歸如何正確輸出樹形菜單

    Java遞歸如何正確輸出樹形菜單

    這篇文章主要為大家詳細(xì)介紹了Java遞歸如何正確輸出樹形菜單,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-02-02
  • java中dart類詳細(xì)講解

    java中dart類詳細(xì)講解

    這篇文章主要介紹了dart類詳細(xì)講解,實(shí)例講解的很清晰,有對于這方面不太清楚的同學(xué)可以跟著學(xué)習(xí)下
    2021-02-02
  • Kafka單節(jié)點(diǎn)偽分布式集群搭建實(shí)現(xiàn)過程詳解

    Kafka單節(jié)點(diǎn)偽分布式集群搭建實(shí)現(xiàn)過程詳解

    這篇文章主要介紹了Kafka單節(jié)點(diǎn)偽分布式集群搭建實(shí)現(xiàn)過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-11-11
  • Java基礎(chǔ)之Spring5的核心之一IOC容器

    Java基礎(chǔ)之Spring5的核心之一IOC容器

    這篇文章主要介紹了Java基礎(chǔ)之Spring5的核心之一IOC容器,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • JAVA+Hibernate 無限級分類

    JAVA+Hibernate 無限級分類

    主要看menu_id和parent_id這兩個字段。 Eclipse生成的表持久映射:(說明:自己加level屬性,作用:為了記錄種類所在深度)
    2008-07-07
  • springboot利用@Aspect實(shí)現(xiàn)日志工具類的詳細(xì)代碼

    springboot利用@Aspect實(shí)現(xiàn)日志工具類的詳細(xì)代碼

    這篇文章主要介紹了springboot利用@Aspect實(shí)現(xiàn)日志工具類,通過實(shí)例代碼介紹了導(dǎo)包及在啟動類上進(jìn)行注解自動掃描的方法,需要的朋友可以參考下
    2022-03-03
  • 實(shí)例講解Java編程中數(shù)組反射的使用方法

    實(shí)例講解Java編程中數(shù)組反射的使用方法

    這篇文章主要介紹了Java編程中數(shù)組反射的使用方法,通過編寫數(shù)組反射工具類可以重用許多基礎(chǔ)代碼,減少對類型的判斷過程,需要的朋友可以參考下
    2016-04-04
  • SpringBoot實(shí)現(xiàn)Thymeleaf驗(yàn)證碼生成

    SpringBoot實(shí)現(xiàn)Thymeleaf驗(yàn)證碼生成

    本文使用SpringBoot實(shí)現(xiàn)Thymeleaf驗(yàn)證碼生成,使用后臺返回驗(yàn)證碼圖片,驗(yàn)證碼存到session中后端實(shí)現(xiàn)校驗(yàn),前端只展示驗(yàn)證碼圖片。感興趣的可以了解下
    2021-05-05
  • 詳解Java如何應(yīng)對常見的安全威脅和攻擊類型

    詳解Java如何應(yīng)對常見的安全威脅和攻擊類型

    隨著信息技術(shù)的快速發(fā)展,網(wǎng)絡(luò)安全問題日益突出,本文將以Java開發(fā)語言為例,深入探討網(wǎng)絡(luò)協(xié)議的安全性問題,通過分析常見的安全威脅和攻擊類型,設(shè)計和實(shí)施安全協(xié)議等主題,為讀者提供一些有益的思路和方法,需要的朋友可以參考下
    2023-11-11

最新評論